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:
345
docs/changelog/PHASE11_IVF_OPTIMIZATION_COMPLETE.md
Normal file
345
docs/changelog/PHASE11_IVF_OPTIMIZATION_COMPLETE.md
Normal file
@@ -0,0 +1,345 @@
|
||||
# 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** 🎉
|
||||
Reference in New Issue
Block a user