# Phase 11 - Optimisation FAISS IVF ✅ COMPLÉTÉ **Date**: 24 Novembre 2024 **Tasks**: 11.2, 11.3 ## 📋 Résumé Implémentation complète de l'optimisation FAISS avec index IVF pour améliorer les performances de recherche de similarité sur de grands volumes d'embeddings. ## ✅ Tâches Complétées ### Task 11.2 : Implémenter caching d'embeddings ✅ **Fichier**: `core/embedding/embedding_cache.py` Implémentation de deux systèmes de cache : #### 1. **EmbeddingCache** - Cache LRU général - Politique d'éviction LRU (Least Recently Used) - Taille maximale configurable (1000 embeddings par défaut) - Limite de mémoire (500 MB par défaut) - Statistiques détaillées (hits/misses/evictions/hit_rate) - Invalidation sélective par clé ou pattern - Estimation de l'utilisation mémoire #### 2. **PrototypeCache** - Cache spécialisé pour prototypes - Optimisé pour les prototypes de WorkflowNodes - Politique d'éviction basée sur la fréquence d'utilisation - Tracking des accès et timestamps - Statistiques d'utilisation **Features**: - ✅ Cache LRU avec éviction automatique - ✅ Gestion de la mémoire - ✅ Statistiques de performance - ✅ Invalidation intelligente --- ### Task 11.3 : Optimiser FAISS avec index IVF ✅ **Fichier**: `core/embedding/faiss_manager.py` Optimisation majeure du système FAISS avec support IVF complet. #### Améliorations Implémentées ##### 1. **Migration Automatique Flat → IVF** ```python # Migration automatique quand >10k embeddings if self.auto_optimize and self.index_type == "Flat": if self.index.ntotal >= self.migration_threshold: self._migrate_to_ivf() ``` - Détection automatique du seuil (10 000 embeddings) - Migration transparente sans perte de données - Préservation des métadonnées - Calcul automatique du nlist optimal ##### 2. **Entraînement Automatique IVF** ```python # Collecte de vecteurs pour entraînement if self.index_type == "IVF" and not self.is_trained: self.training_vectors.append(vector_float32) if len(self.training_vectors) >= 100: self._train_ivf_index() ``` - Collecte automatique des premiers 100 vecteurs - Entraînement automatique dès que suffisant de données - Ajout automatique des vecteurs d'entraînement à l'index ##### 3. **Calcul Optimal de nlist** ```python def _calculate_nlist(self, n_vectors: int) -> int: """Règle empirique: nlist = sqrt(n_vectors)""" nlist = int(np.sqrt(n_vectors)) return max(100, min(nlist, 65536)) ``` - Formule empirique : `nlist = √n_vectors` - Contraintes : min=100, max=65536 - Adaptation dynamique à la taille de l'index ##### 4. **Optimisation Périodique** ```python def optimize_index(self): """Recalculer nlist optimal et réentraîner si nécessaire""" optimal_nlist = self._calculate_nlist(n_vectors) if abs(optimal_nlist - current_nlist) / current_nlist > 0.5: # Reconstruire l'index avec nlist optimal ``` - Détection de nlist sous-optimal (>50% de différence) - Reconstruction automatique de l'index - Réentraînement avec tous les vecteurs ##### 5. **Support GPU (Préparé)** ```python def _setup_gpu(self): """Configurer les ressources GPU si disponibles""" ngpus = faiss.get_num_gpus() if ngpus > 0: self.gpu_resources = faiss.StandardGpuResources() ``` - Détection automatique des GPUs disponibles - Migration CPU ↔ GPU transparente - Fallback automatique sur CPU si GPU indisponible ##### 6. **DirectMap pour Reconstruction** ```python # Activer DirectMap pour permettre reconstruct() index.make_direct_map() ``` - Permet la reconstruction de vecteurs depuis l'index - Nécessaire pour l'optimisation périodique - Activé automatiquement sur tous les index IVF #### Paramètres Configurables ```python FAISSManager( dimensions=512, index_type="IVF", # "Flat", "IVF", "HNSW" metric="cosine", # "cosine", "l2", "ip" nlist=None, # Auto si None nprobe=8, # Nombre de clusters à visiter use_gpu=False, # Utiliser GPU si disponible auto_optimize=True # Migration auto Flat→IVF ) ``` #### Statistiques Enrichies ```python stats = manager.get_stats() # { # "dimensions": 512, # "index_type": "IVF", # "metric": "cosine", # "total_vectors": 15000, # "is_trained": True, # "nlist": 122, # "nprobe": 8, # "optimal_nlist": 122, # "nlist_efficiency": 1.0, # "use_gpu": False # } ``` --- ## 🧪 Tests **Fichier**: `tests/unit/test_faiss_ivf_optimization.py` ### 8 Tests Complets - Tous Passent ✅ 1. ✅ **test_ivf_training** - Entraînement automatique 2. ✅ **test_nlist_calculation** - Calcul de nlist optimal 3. ✅ **test_auto_migration_flat_to_ivf** - Migration automatique 4. ✅ **test_ivf_search_quality** - Qualité de recherche IVF 5. ✅ **test_ivf_nprobe_effect** - Effet de nprobe sur qualité 6. ✅ **test_optimize_index** - Optimisation périodique 7. ✅ **test_save_load_ivf** - Sauvegarde/chargement IVF 8. ✅ **test_stats_with_ivf** - Statistiques IVF ```bash $ pytest tests/unit/test_faiss_ivf_optimization.py -v ======================== 8 passed in 3.84s ======================== ``` --- ## 📊 Performances Attendues ### Comparaison Flat vs IVF | Métrique | Flat | IVF (nlist=100, nprobe=8) | |----------|------|---------------------------| | **Recherche (10k vecteurs)** | ~50ms | ~5-10ms | | **Recherche (100k vecteurs)** | ~500ms | ~10-20ms | | **Recherche (1M vecteurs)** | ~5s | ~20-50ms | | **Mémoire** | 100% | ~100% + overhead | | **Précision** | 100% | ~95-99% | ### Recommandations - **< 10k embeddings** : Utiliser Flat (recherche exacte) - **10k - 100k embeddings** : Utiliser IVF avec nprobe=8 - **> 100k embeddings** : Utiliser IVF avec nprobe=16-32 - **> 1M embeddings** : Considérer IVF avec GPU --- ## 🔧 Utilisation ### Exemple 1 : Migration Automatique ```python from core.embedding.faiss_manager import FAISSManager # Créer index Flat avec auto-migration manager = FAISSManager( dimensions=512, index_type="Flat", auto_optimize=True # Migration auto vers IVF ) # Ajouter des embeddings for i in range(15000): vector = compute_embedding(data[i]) manager.add_embedding(f"emb_{i}", vector) # Automatiquement migré vers IVF après 10k embeddings print(manager.index_type) # "IVF" ``` ### Exemple 2 : IVF Direct ```python # Créer index IVF directement manager = FAISSManager( dimensions=512, index_type="IVF", metric="cosine", nlist=100, # Sera ajusté automatiquement nprobe=8 # Compromis vitesse/qualité ) # Ajouter embeddings (entraînement auto après 100) for i in range(1000): manager.add_embedding(f"emb_{i}", vectors[i]) # Rechercher results = manager.search_similar(query_vector, k=10) ``` ### Exemple 3 : Optimisation Périodique ```python # Après avoir ajouté beaucoup de vecteurs manager.optimize_index() # Vérifier l'efficacité stats = manager.get_stats() print(f"nlist efficiency: {stats['nlist_efficiency']:.2%}") ``` ### Exemple 4 : Avec Cache ```python from core.embedding.embedding_cache import EmbeddingCache, PrototypeCache # Créer caches embedding_cache = EmbeddingCache(max_size=1000, max_memory_mb=500) prototype_cache = PrototypeCache(max_size=100) # Utiliser avec FAISS def get_embedding(embedding_id): # Vérifier cache d'abord vector = embedding_cache.get(embedding_id) if vector is not None: return vector # Charger depuis FAISS vector = load_from_faiss(embedding_id) # Mettre en cache embedding_cache.put(embedding_id, vector) return vector # Statistiques stats = embedding_cache.get_stats() print(f"Hit rate: {stats['hit_rate']:.2%}") ``` --- ## 📈 Impact sur le Système ### Avant (Flat uniquement) - ❌ Recherche lente sur >10k embeddings - ❌ Pas de cache - ❌ Pas d'optimisation automatique ### Après (IVF + Cache) - ✅ Recherche 10-50x plus rapide avec IVF - ✅ Cache LRU réduit les accès disque - ✅ Migration automatique Flat→IVF - ✅ Optimisation périodique automatique - ✅ Support GPU préparé - ✅ Statistiques détaillées --- ## 🎯 Prochaines Étapes La Task 11.4 est la suivante : - **11.4** : Optimiser détection UI avec ROI --- ## 📝 Notes Techniques ### Choix de nprobe Le paramètre `nprobe` contrôle le compromis vitesse/qualité : - **nprobe=1** : Très rapide, qualité ~80% - **nprobe=8** : Bon compromis, qualité ~95% - **nprobe=16** : Plus lent, qualité ~98% - **nprobe=nlist** : Équivalent à Flat (100%) ### DirectMap L'activation de DirectMap permet : - Reconstruction de vecteurs depuis l'index - Nécessaire pour `optimize_index()` - Overhead mémoire : ~8 bytes par vecteur ### Normalisation Pour la métrique cosine : - Vecteurs normalisés automatiquement - Utilise inner product (IP) en interne - Distance = similarité cosinus --- ## ✅ Validation - [x] Task 11.2 : Cache d'embeddings implémenté - [x] Task 11.3 : Optimisation IVF complète - [x] 8/8 tests passent - [x] Migration automatique fonctionne - [x] Entraînement automatique fonctionne - [x] Optimisation périodique fonctionne - [x] Sauvegarde/chargement IVF fonctionne - [x] Statistiques enrichies - [x] Documentation complète **Phase 11 (Optimisation FAISS) : 100% COMPLÈTE** 🎉