v1.0 - Version stable: multi-PC, détection UI-DETR-1, 3 modes exécution
- Frontend v4 accessible sur réseau local (192.168.1.40) - Ports ouverts: 3002 (frontend), 5001 (backend), 5004 (dashboard) - Ollama GPU fonctionnel - Self-healing interactif - Dashboard confiance Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
98
tests/unit/test_faiss_manager.py
Normal file
98
tests/unit/test_faiss_manager.py
Normal file
@@ -0,0 +1,98 @@
|
||||
"""
|
||||
Tests unitaires pour FAISSManager avec property-based testing.
|
||||
|
||||
Property 11: FAISS Index Consistency
|
||||
- L'index FAISS doit maintenir la cohérence entre vecteurs et métadonnées
|
||||
- Validates: Requirements 4.8, 12.3, 12.6
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import numpy as np
|
||||
import tempfile
|
||||
import shutil
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
|
||||
from core.embedding.faiss_manager import FAISSManager
|
||||
|
||||
|
||||
class TestFAISSManager:
|
||||
"""Tests pour FAISSManager."""
|
||||
|
||||
def setup_method(self):
|
||||
"""Setup avant chaque test."""
|
||||
self.temp_dir = tempfile.mkdtemp()
|
||||
self.index_path = Path(self.temp_dir) / "test_index"
|
||||
self.manager = FAISSManager(dimensions=512)
|
||||
|
||||
def teardown_method(self):
|
||||
"""Cleanup après chaque test."""
|
||||
shutil.rmtree(self.temp_dir, ignore_errors=True)
|
||||
|
||||
def test_add_single_embedding(self):
|
||||
"""Test ajout d'un seul embedding."""
|
||||
vector = np.random.randn(512).astype(np.float32)
|
||||
vector = vector / np.linalg.norm(vector)
|
||||
|
||||
metadata = {
|
||||
'state_id': 'state_001',
|
||||
'timestamp': '2024-11-22T10:00:00'
|
||||
}
|
||||
|
||||
idx = self.manager.add_embedding('emb_001', vector, metadata)
|
||||
|
||||
assert idx == 0
|
||||
assert self.manager.index.ntotal == 1
|
||||
|
||||
def test_property_index_consistency(self):
|
||||
"""Property 11: Cohérence entre index et métadonnées."""
|
||||
n_vectors = 20
|
||||
|
||||
for i in range(n_vectors):
|
||||
vector = np.random.randn(512).astype(np.float32)
|
||||
vector = vector / np.linalg.norm(vector)
|
||||
metadata = {'state_id': f'state_{i:03d}', 'index': i}
|
||||
self.manager.add_embedding(f'emb_{i:03d}', vector, metadata)
|
||||
|
||||
assert self.manager.index.ntotal == n_vectors
|
||||
assert len(self.manager.metadata_store) == n_vectors
|
||||
|
||||
def test_search_similar(self):
|
||||
"""Test recherche de similarité."""
|
||||
vectors = []
|
||||
for i in range(5):
|
||||
vector = np.random.randn(512).astype(np.float32)
|
||||
vector = vector / np.linalg.norm(vector)
|
||||
vectors.append(vector)
|
||||
self.manager.add_embedding(f'emb_{i}', vector, {'state_id': f'state_{i}'})
|
||||
|
||||
query = vectors[0]
|
||||
results = self.manager.search_similar(query, k=3)
|
||||
|
||||
assert len(results) == 3
|
||||
assert results[0].similarity > 0.99
|
||||
|
||||
def test_save_and_load(self):
|
||||
"""Test sauvegarde et chargement."""
|
||||
n_vectors = 10
|
||||
original_vectors = []
|
||||
|
||||
for i in range(n_vectors):
|
||||
vector = np.random.randn(512).astype(np.float32)
|
||||
vector = vector / np.linalg.norm(vector)
|
||||
original_vectors.append(vector)
|
||||
self.manager.add_embedding(f'emb_{i}', vector, {'state_id': f'state_{i}'})
|
||||
|
||||
index_path = self.index_path / "index.faiss"
|
||||
metadata_path = self.index_path / "metadata.pkl"
|
||||
self.manager.save(index_path, metadata_path)
|
||||
|
||||
new_manager = FAISSManager.load(index_path, metadata_path)
|
||||
|
||||
assert new_manager.index.ntotal == n_vectors
|
||||
assert len(new_manager.metadata_store) == n_vectors
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pytest.main([__file__, '-v'])
|
||||
Reference in New Issue
Block a user