Initial commit

This commit is contained in:
Dom
2026-03-05 00:20:25 +01:00
commit dcd4de9945
1954 changed files with 669380 additions and 0 deletions

View File

@@ -0,0 +1,508 @@
# Design - Amélioration du Système d'Embeddings et Fine-tuning
## Overview
Le système d'embeddings actuel utilise CLIP avec FAISS mais souffre de problèmes de dimensions et de performance. Cette amélioration corrige FAISS, crée une abstraction pour supporter plusieurs modèles (CLIP baseline, Pix2Struct pour UI), et ajoute un fine-tuning léger incrémental qui s'exécute toutes les 10 nouvelles interactions pour améliorer la précision.
## Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ Embedding System │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ EmbedderBase │◄─────│ CLIPEmbedder │ │
│ │ (Abstract) │ └──────────────┘ │
│ └──────┬───────┘ │
│ │ │
│ │ ┌────────────────────┐ │
│ └──────────────│ Pix2StructEmbedder │ │
│ └────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ EmbeddingManager │ │
│ │ - Model selection & fallback │ │
│ │ - Caching (LRU 1000 entries) │ │
│ │ - GPU/CPU management │ │
│ └────────────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ FAISSIndex │ │
│ │ - Fixed dimension handling │ │
│ │ - Persistence (index + metadata) │ │
│ │ - Auto-rebuild on dimension change │ │
│ └────────────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ LightweightFineTuner │ │
│ │ - Collects positive/negative examples │ │
│ │ - Triggers every 10 examples │ │
│ │ - Runs in background thread │ │
│ │ - Updates last layer only │ │
│ └────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
WorkflowMatcher VisionAnalysis SessionManager
```
## Components and Interfaces
### 1. EmbedderBase (Abstract Interface)
**Responsabilité**: Interface commune pour tous les modèles d'embedding
```python
from abc import ABC, abstractmethod
from PIL import Image
import numpy as np
class EmbedderBase(ABC):
@abstractmethod
def embed(self, image: Image.Image) -> np.ndarray:
"""Generate embedding for an image
Returns:
np.ndarray: Normalized embedding vector
"""
pass
@abstractmethod
def get_dimension(self) -> int:
"""Get embedding dimension"""
pass
@abstractmethod
def get_model_name(self) -> str:
"""Get model identifier"""
pass
@abstractmethod
def supports_batch(self) -> bool:
"""Check if model supports batch processing"""
pass
def embed_batch(self, images: List[Image.Image]) -> np.ndarray:
"""Generate embeddings for multiple images (optional optimization)"""
return np.array([self.embed(img) for img in images])
```
### 2. CLIPEmbedder (Concrete Implementation)
**Responsabilité**: Wrapper pour CLIP avec l'interface commune
```python
class CLIPEmbedder(EmbedderBase):
def __init__(self, device='cuda' if torch.cuda.is_available() else 'cpu'):
self.device = device
self.model, self.preprocess = clip.load("ViT-B/32", device=device)
self.model.eval()
def embed(self, image: Image.Image) -> np.ndarray:
with torch.no_grad():
image_tensor = self.preprocess(image).unsqueeze(0).to(self.device)
embedding = self.model.encode_image(image_tensor)
embedding = embedding / embedding.norm(dim=-1, keepdim=True)
return embedding.cpu().numpy().flatten()
def get_dimension(self) -> int:
return 512 # CLIP ViT-B/32 dimension
def get_model_name(self) -> str:
return "clip-vit-b32"
def supports_batch(self) -> bool:
return True
```
### 3. Pix2StructEmbedder (Concrete Implementation)
**Responsabilité**: Wrapper pour Pix2Struct spécialisé UI
```python
from transformers import Pix2StructProcessor, Pix2StructForConditionalGeneration
class Pix2StructEmbedder(EmbedderBase):
def __init__(self, device='cuda' if torch.cuda.is_available() else 'cpu'):
self.device = device
self.processor = Pix2StructProcessor.from_pretrained(
"google/pix2struct-base"
)
self.model = Pix2StructForConditionalGeneration.from_pretrained(
"google/pix2struct-base"
).to(device)
self.model.eval()
def embed(self, image: Image.Image) -> np.ndarray:
with torch.no_grad():
inputs = self.processor(images=image, return_tensors="pt").to(self.device)
# Extract encoder hidden states as embeddings
encoder_outputs = self.model.encoder(**inputs)
embedding = encoder_outputs.last_hidden_state.mean(dim=1)
embedding = embedding / embedding.norm(dim=-1, keepdim=True)
return embedding.cpu().numpy().flatten()
def get_dimension(self) -> int:
return 768 # Pix2Struct base dimension
def get_model_name(self) -> str:
return "pix2struct-base"
def supports_batch(self) -> bool:
return True
```
### 4. EmbeddingManager
**Responsabilité**: Gestion des modèles, cache, et sélection
```python
from functools import lru_cache
from typing import Optional
class EmbeddingManager:
def __init__(self, model_name: str = "clip", fallback: bool = True):
self.model_name = model_name
self.fallback_enabled = fallback
self.embedder = self._load_embedder()
self._cache = {} # Manual LRU cache
self._cache_order = []
self.max_cache_size = 1000
def _load_embedder(self) -> EmbedderBase:
"""Load embedder with fallback"""
try:
if self.model_name == "pix2struct":
return Pix2StructEmbedder()
elif self.model_name == "clip":
return CLIPEmbedder()
else:
raise ValueError(f"Unknown model: {self.model_name}")
except Exception as e:
if self.fallback_enabled:
logger.warning(f"Failed to load {self.model_name}, falling back to CLIP: {e}")
return CLIPEmbedder()
raise
def embed(self, image: Image.Image) -> np.ndarray:
"""Generate embedding with caching"""
# Create cache key from image hash
img_hash = hashlib.md5(image.tobytes()).hexdigest()
if img_hash in self._cache:
return self._cache[img_hash]
# Generate embedding
embedding = self.embedder.embed(image)
# Update cache
self._cache[img_hash] = embedding
self._cache_order.append(img_hash)
# Evict if needed
if len(self._cache) > self.max_cache_size:
oldest = self._cache_order.pop(0)
del self._cache[oldest]
return embedding
def get_dimension(self) -> int:
return self.embedder.get_dimension()
def get_model_name(self) -> str:
return self.embedder.get_model_name()
```
### 5. FAISSIndex (Fixed)
**Responsabilité**: Gestion de l'index FAISS avec correction des bugs
```python
import faiss
import pickle
class FAISSIndex:
def __init__(self, dimension: int):
self.dimension = dimension
self.index = faiss.IndexFlatL2(dimension)
self.metadata = [] # Store workflow IDs and step info
def add(self, embeddings: np.ndarray, metadata: List[dict]):
"""Add embeddings to index
Args:
embeddings: Shape (N, dimension)
metadata: List of N metadata dicts
"""
if embeddings.shape[1] != self.dimension:
raise ValueError(
f"Embedding dimension {embeddings.shape[1]} doesn't match "
f"index dimension {self.dimension}"
)
self.index.add(embeddings.astype('float32'))
self.metadata.extend(metadata)
def search(self, query: np.ndarray, k: int = 5) -> List[dict]:
"""Search for similar embeddings
Args:
query: Shape (1, dimension) or (dimension,)
k: Number of results
Returns:
List of dicts with 'distance', 'metadata'
"""
if query.ndim == 1:
query = query.reshape(1, -1)
if query.shape[1] != self.dimension:
raise ValueError(
f"Query dimension {query.shape[1]} doesn't match "
f"index dimension {self.dimension}"
)
distances, indices = self.index.search(query.astype('float32'), k)
results = []
for dist, idx in zip(distances[0], indices[0]):
if idx < len(self.metadata):
results.append({
'distance': float(dist),
'similarity': 1.0 / (1.0 + dist), # Convert to similarity
'metadata': self.metadata[idx]
})
return results
def save(self, path: str):
"""Save index and metadata"""
faiss.write_index(self.index, f"{path}.index")
with open(f"{path}.metadata", 'wb') as f:
pickle.dump({
'dimension': self.dimension,
'metadata': self.metadata
}, f)
def load(self, path: str):
"""Load index and metadata"""
self.index = faiss.read_index(f"{path}.index")
with open(f"{path}.metadata", 'rb') as f:
data = pickle.load(f)
self.dimension = data['dimension']
self.metadata = data['metadata']
def rebuild_if_needed(self, new_dimension: int):
"""Rebuild index if dimension changed"""
if new_dimension != self.dimension:
logger.info(f"Rebuilding FAISS index: {self.dimension} -> {new_dimension}")
old_metadata = self.metadata
self.dimension = new_dimension
self.index = faiss.IndexFlatL2(new_dimension)
self.metadata = []
# Note: Old embeddings are lost, need to regenerate
return True
return False
```
### 6. LightweightFineTuner
**Responsabilité**: Fine-tuning incrémental en arrière-plan
```python
import threading
from collections import deque
class LightweightFineTuner:
def __init__(self, embedder: EmbedderBase, trigger_threshold: int = 10):
self.embedder = embedder
self.trigger_threshold = trigger_threshold
self.positive_examples = deque(maxlen=1000)
self.negative_examples = deque(maxlen=1000)
self.is_training = False
self.training_thread = None
def add_positive_example(self, image: Image.Image, workflow_id: str):
"""Add successful workflow execution example"""
self.positive_examples.append({
'image': image,
'workflow_id': workflow_id,
'timestamp': time.time()
})
self._check_trigger()
def add_negative_example(self, image: Image.Image, workflow_id: str):
"""Add rejected workflow suggestion example"""
self.negative_examples.append({
'image': image,
'workflow_id': workflow_id,
'timestamp': time.time()
})
self._check_trigger()
def _check_trigger(self):
"""Check if we should trigger fine-tuning"""
total_new = len(self.positive_examples) + len(self.negative_examples)
if total_new >= self.trigger_threshold and not self.is_training:
logger.info(f"Triggering fine-tuning with {total_new} new examples")
self._start_training()
def _start_training(self):
"""Start training in background thread"""
self.training_thread = threading.Thread(target=self._train)
self.training_thread.daemon = True
self.training_thread.start()
def _train(self):
"""Fine-tune the last layer of the model"""
self.is_training = True
try:
# Only for models that support fine-tuning (not CLIP base)
if not hasattr(self.embedder, 'fine_tune'):
logger.info("Model doesn't support fine-tuning, skipping")
return
# Prepare training data
positive_images = [ex['image'] for ex in self.positive_examples]
negative_images = [ex['image'] for ex in self.negative_examples]
# Fine-tune (implementation depends on model)
metrics = self.embedder.fine_tune(
positive_images=positive_images,
negative_images=negative_images,
epochs=1,
learning_rate=1e-4
)
logger.info(f"Fine-tuning complete: {metrics}")
# Clear examples after training
self.positive_examples.clear()
self.negative_examples.clear()
except Exception as e:
logger.error(f"Fine-tuning failed: {e}")
finally:
self.is_training = False
def save_checkpoint(self, path: str):
"""Save training examples for recovery"""
with open(path, 'wb') as f:
pickle.dump({
'positive': list(self.positive_examples),
'negative': list(self.negative_examples)
}, f)
def load_checkpoint(self, path: str):
"""Load training examples"""
with open(path, 'rb') as f:
data = pickle.load(f)
self.positive_examples.extend(data['positive'])
self.negative_examples.extend(data['negative'])
```
## Data Models
### EmbeddingMetadata
```python
@dataclass
class EmbeddingMetadata:
workflow_id: str
step_index: int
action_type: str
timestamp: float
model_name: str
model_version: str
```
### FineTuningMetrics
```python
@dataclass
class FineTuningMetrics:
loss: float
accuracy: float
positive_examples: int
negative_examples: int
duration_seconds: float
timestamp: float
```
## Correctness Properties
*A property is a characteristic or behavior that should hold true across all valid executions of a system-essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.*
### Property 1: Embedding Dimension Consistency
*For any* embedder instance, all generated embeddings SHALL have the same dimension as reported by `get_dimension()`
**Validates: Requirements 1.1, 2.2, 3.3**
### Property 2: FAISS Index Persistence Round-trip
*For any* FAISS index with embeddings, saving then loading SHALL restore the exact same search results
**Validates: Requirements 1.3, 1.4**
### Property 3: Embedder Interface Compatibility
*For any* embedder implementation (CLIP or Pix2Struct), calling `embed()` with a valid PIL image SHALL return a normalized numpy array
**Validates: Requirements 2.1, 2.2, 2.5**
### Property 4: Cache Hit Consistency
*For any* image, generating embeddings twice SHALL return identical results (via caching)
**Validates: Requirements 6.1**
### Property 5: Fallback Reliability
*For any* model loading failure, if fallback is enabled, the system SHALL successfully load CLIP without raising exceptions
**Validates: Requirements 2.4, 3.5**
### Property 6: Fine-tuning Non-blocking
*For any* fine-tuning operation, the main thread SHALL continue generating embeddings without blocking
**Validates: Requirements 5.1, 5.2**
### Property 7: Example Collection Bounds
*For any* sequence of positive/negative examples, the collection SHALL never exceed 1000 examples (deque maxlen)
**Validates: Requirements 4.1, 4.2**
## Error Handling
- **Model loading fails**: Fallback to CLIP if enabled, otherwise raise clear error
- **Dimension mismatch**: Rebuild FAISS index automatically, log warning
- **GPU unavailable**: Fall back to CPU seamlessly
- **Fine-tuning fails**: Log error, keep current model, don't crash
- **Cache overflow**: Evict LRU entries automatically
- **Corrupted index file**: Rebuild from scratch, log error
## Testing Strategy
### Unit Tests
- Test each embedder implementation independently
- Test FAISS index add/search/save/load operations
- Test cache eviction logic
- Test dimension mismatch handling
- Test fallback mechanism
### Property-Based Tests
- Property 1: Dimension consistency across random images
- Property 2: FAISS round-trip with random embeddings
- Property 3: Interface compatibility with random PIL images
- Property 4: Cache consistency with duplicate images
- Property 5: Fallback with simulated failures
- Property 6: Fine-tuning non-blocking with concurrent operations
- Property 7: Example collection bounds with random additions
### Integration Tests
- Test full workflow: image → embedding → FAISS → search
- Test model switching (CLIP ↔ Pix2Struct)
- Test fine-tuning trigger and execution
- Test system behavior under GPU/CPU switching
## Performance
- **Embedding generation**: < 200ms per image (GPU), < 500ms (CPU)
- **FAISS search**: < 10ms for k=5 in index of 10,000 embeddings
- **Cache hit**: < 1ms
- **Fine-tuning**: < 2 minutes for 100 examples
- **Model loading**: < 5 seconds (CLIP), < 10 seconds (Pix2Struct)
- **Memory usage**: ~2GB (CLIP), ~4GB (Pix2Struct), ~500MB (FAISS index for 10k embeddings)

View File

@@ -0,0 +1,102 @@
# Requirements - Amélioration du Système d'Embeddings et Fine-tuning
## Introduction
Ce document spécifie les exigences pour améliorer le système d'embeddings visuels utilisé pour le matching de workflows. Le système doit corriger les problèmes FAISS actuels, créer une abstraction pour supporter plusieurs modèles (CLIP, Pix2Struct), et implémenter un fine-tuning léger incrémental pour améliorer la précision au fil du temps.
## Glossary
- **Embedding**: Représentation vectorielle d'une image capturée d'écran
- **FAISS**: Bibliothèque Facebook AI pour la recherche de similarité vectorielle
- **CLIP**: Modèle vision-language d'OpenAI pour les embeddings génériques
- **Pix2Struct**: Modèle Google spécialisé pour la compréhension d'interfaces utilisateur
- **Fine-tuning Léger**: Ajustement incrémental de la dernière couche du modèle
- **Embedder**: Interface abstraite pour générer des embeddings d'images
- **Workflow Match**: Correspondance entre une situation actuelle et un workflow connu
## Requirements
### Requirement 1
**User Story:** As a developer, I want the FAISS embedding system to work correctly, so that workflow matching can function reliably.
#### Acceptance Criteria
1. WHEN the system generates embeddings THEN the FAISS index SHALL store them without dimension errors
2. WHEN the system searches for similar embeddings THEN FAISS SHALL return results with valid similarity scores
3. WHEN embeddings are saved to disk THEN the system SHALL persist both the index and metadata correctly
4. WHEN embeddings are loaded from disk THEN the system SHALL restore the exact same index state
5. WHEN the embedding dimension changes THEN the system SHALL rebuild the index automatically
### Requirement 2
**User Story:** As a developer, I want an abstraction layer for embedding models, so that I can easily switch between CLIP and Pix2Struct.
#### Acceptance Criteria
1. WHEN creating an embedder THEN the system SHALL provide a common interface for all models
2. WHEN generating embeddings THEN the interface SHALL accept PIL images and return numpy arrays
3. WHEN switching models THEN the system SHALL maintain backward compatibility with existing workflows
4. WHEN a model fails to load THEN the system SHALL fallback to CLIP automatically
5. WHEN using different models THEN the system SHALL normalize embeddings to comparable scales
### Requirement 3
**User Story:** As a user, I want Pix2Struct to be available as an embedding model, so that UI matching accuracy improves over CLIP.
#### Acceptance Criteria
1. WHEN Pix2Struct is selected THEN the system SHALL load the model on first use
2. WHEN generating embeddings with Pix2Struct THEN the system SHALL use GPU if available
3. WHEN Pix2Struct generates embeddings THEN they SHALL have consistent dimensions
4. WHEN comparing Pix2Struct and CLIP THEN Pix2Struct SHALL show better UI element recognition
5. WHEN Pix2Struct is unavailable THEN the system SHALL fallback to CLIP without errors
### Requirement 4
**User Story:** As a user, I want the system to learn from my usage patterns, so that workflow matching improves over time.
#### Acceptance Criteria
1. WHEN a workflow is successfully executed THEN the system SHALL collect the screen embeddings as positive examples
2. WHEN a workflow suggestion is rejected THEN the system SHALL collect the screen embeddings as negative examples
3. WHEN 10 new examples are collected THEN the system SHALL trigger a lightweight fine-tuning update
4. WHEN fine-tuning runs THEN the system SHALL complete within 2 minutes
5. WHEN fine-tuning completes THEN the system SHALL update the model weights without restarting
### Requirement 5
**User Story:** As a user, I want fine-tuning to happen in the background, so that it doesn't interrupt my work.
#### Acceptance Criteria
1. WHEN fine-tuning is triggered THEN the system SHALL run it in a separate thread
2. WHEN fine-tuning is running THEN the system SHALL continue using the current model
3. WHEN fine-tuning completes THEN the system SHALL swap to the new model atomically
4. WHEN fine-tuning fails THEN the system SHALL log the error and keep the current model
5. WHEN the system shuts down during fine-tuning THEN the system SHALL save partial progress
### Requirement 6
**User Story:** As a developer, I want the embedding system to be efficient, so that it doesn't slow down the application.
#### Acceptance Criteria
1. WHEN generating embeddings THEN the system SHALL cache results for identical images
2. WHEN the cache exceeds 1000 entries THEN the system SHALL evict least recently used entries
3. WHEN using GPU THEN the system SHALL batch multiple embedding requests
4. WHEN GPU is unavailable THEN the system SHALL use CPU without errors
5. WHEN measuring performance THEN embedding generation SHALL take less than 200ms per image
### Requirement 7
**User Story:** As a user, I want to see which embedding model is being used, so that I can understand system behavior.
#### Acceptance Criteria
1. WHEN the system starts THEN the system SHALL log which embedding model is loaded
2. WHEN fine-tuning completes THEN the system SHALL log the improvement metrics
3. WHEN switching models THEN the system SHALL notify the user via logs
4. WHEN embeddings are generated THEN the system SHALL include model metadata
5. WHEN debugging THEN the system SHALL provide embedding visualization tools

View File

@@ -0,0 +1,306 @@
# Implementation Plan - Amélioration du Système d'Embeddings et Fine-tuning
## Phase 1: Fix FAISS et Abstraction de Base
- [x] 1. Créer l'abstraction EmbedderBase
- Créer `geniusia2/core/embedders/__init__.py`
- Créer `geniusia2/core/embedders/base.py` avec classe abstraite `EmbedderBase`
- Définir méthodes: `embed()`, `get_dimension()`, `get_model_name()`, `supports_batch()`, `embed_batch()`
- Ajouter docstrings complètes
- _Requirements: 2.1, 2.2_
- [x] 2. Implémenter CLIPEmbedder
- Créer `geniusia2/core/embedders/clip_embedder.py`
- Wrapper autour du code CLIP existant dans `vision_analysis.py`
- Implémenter toutes les méthodes de `EmbedderBase`
- Gérer GPU/CPU automatiquement
- Normaliser les embeddings (L2 norm)
- _Requirements: 2.1, 2.2, 2.5, 6.4_
- [x] 3. Créer FAISSIndex corrigé
- Créer `geniusia2/core/embedders/faiss_index.py`
- Implémenter `add()` avec validation de dimension
- Implémenter `search()` avec conversion distance→similarity
- Implémenter `save()` et `load()` avec metadata
- Implémenter `rebuild_if_needed()` pour changement de dimension
- Gérer les cas d'erreur (dimension mismatch, fichier corrompu)
- _Requirements: 1.1, 1.2, 1.3, 1.4, 1.5_
- [ ]* 3.1 Écrire tests unitaires pour FAISSIndex
- Test add/search avec différentes dimensions
- Test save/load round-trip
- Test rebuild sur changement de dimension
- Test gestion d'erreurs
- _Requirements: 1.1, 1.2, 1.3, 1.4, 1.5_
- [ ]* 3.2 Écrire test de propriété pour FAISS round-trip
- **Property 2: FAISS Index Persistence Round-trip**
- **Validates: Requirements 1.3, 1.4**
- Générer embeddings aléatoires, sauvegarder, charger, vérifier résultats identiques
- [x] 4. Créer EmbeddingManager
- Créer `geniusia2/core/embedders/embedding_manager.py`
- Implémenter sélection de modèle avec fallback
- Implémenter cache LRU manuel (1000 entrées)
- Utiliser hash MD5 de l'image comme clé de cache
- Logger le modèle chargé au démarrage
- _Requirements: 2.3, 2.4, 6.1, 6.2, 7.1, 7.3_
- [ ]* 4.1 Écrire tests pour EmbeddingManager
- Test sélection de modèle
- Test fallback sur erreur
- Test cache hit/miss
- Test éviction LRU
- _Requirements: 2.4, 6.1, 6.2_
- [ ]* 4.2 Écrire test de propriété pour cache consistency
- **Property 4: Cache Hit Consistency**
- **Validates: Requirements 6.1**
- Générer images aléatoires, embedder 2x, vérifier résultats identiques
- [x] 5. Intégrer dans vision_analysis.py
- Remplacer le code CLIP direct par `EmbeddingManager`
- Ajouter paramètre de config pour choisir le modèle (clip/pix2struct)
- Migrer les embeddings existants si nécessaire
- Maintenir backward compatibility
- _Requirements: 2.3, 2.4_
- [x] 6. Intégrer dans workflow_matcher.py
- Utiliser `EmbeddingManager` au lieu de CLIP direct
- Utiliser `FAISSIndex` pour les recherches de similarité
- Gérer le cas où l'index n'existe pas encore
- _Requirements: 1.1, 1.2_
- [x] 7. Checkpoint - Tester le système de base
- Lancer l'application en mode Assist
- Vérifier que les embeddings sont générés correctement
- Vérifier que FAISS fonctionne sans erreurs de dimension
- Vérifier que le cache fonctionne
- Tester save/load de l'index FAISS
- Ensure all tests pass, ask the user if questions arise.
## Phase 2: Ajouter Pix2Struct
- [x] 8. Installer dépendances Pix2Struct
- Ajouter `transformers>=4.35.0` à requirements
- Ajouter `sentencepiece` à requirements
- Créer script d'installation `install_pix2struct.sh`
- Tester l'installation sur la machine cible
- _Requirements: 3.1_
- [x] 9. Implémenter Pix2StructEmbedder
- Créer `geniusia2/core/embedders/pix2struct_embedder.py`
- Charger le modèle `google/pix2struct-base`
- Extraire les hidden states de l'encoder comme embeddings
- Normaliser les embeddings (L2 norm)
- Gérer GPU/CPU automatiquement
- Implémenter toutes les méthodes de `EmbedderBase`
- _Requirements: 3.1, 3.2, 3.3, 3.5_
- [ ]* 9.1 Écrire tests pour Pix2StructEmbedder
- Test chargement du modèle
- Test génération d'embeddings
- Test dimension consistency
- Test GPU/CPU switching
- _Requirements: 3.1, 3.2, 3.3_
- [ ]* 9.2 Écrire test de propriété pour interface compatibility
- **Property 3: Embedder Interface Compatibility**
- **Validates: Requirements 2.1, 2.2, 2.5**
- Tester CLIP et Pix2Struct avec images PIL aléatoires, vérifier format de sortie
- [x] 10. Tester Pix2Struct vs CLIP
- Créer script de benchmark `test_pix2struct_vs_clip.py`
- Comparer la qualité des embeddings sur des screenshots UI
- Mesurer les performances (temps, mémoire)
- Documenter les résultats
- _Requirements: 3.4, 6.5_
- [x] 11. Ajouter configuration pour sélection de modèle
- Ajouter paramètre `embedding_model` dans config
- Valeurs possibles: "clip", "pix2struct"
- Défaut: "clip" (pour compatibilité)
- Documenter dans README
- _Requirements: 2.3, 7.1_
- [x] 12. Checkpoint - Tester Pix2Struct
- Lancer avec `embedding_model=pix2struct`
- Vérifier que le modèle charge correctement
- Comparer la précision du matching avec CLIP
- Vérifier le fallback si Pix2Struct échoue
- Ensure all tests pass, ask the user if questions arise.
## Phase 3: Fine-tuning Léger
- [x] 13. Créer LightweightFineTuner
- Créer `geniusia2/core/embedders/fine_tuner.py`
- Implémenter collection d'exemples positifs/négatifs (deque maxlen=1000)
- Implémenter trigger automatique tous les 10 exemples
- Implémenter exécution en thread séparé
- Implémenter sauvegarde/chargement de checkpoint
- _Requirements: 4.1, 4.2, 4.3, 5.1, 5.5_
- [ ]* 13.1 Écrire tests pour LightweightFineTuner
- Test collection d'exemples
- Test trigger threshold
- Test thread séparé (non-blocking)
- Test checkpoint save/load
- _Requirements: 4.1, 4.2, 4.3, 5.1_
- [ ]* 13.2 Écrire test de propriété pour example collection bounds
- **Property 7: Example Collection Bounds**
- **Validates: Requirements 4.1, 4.2**
- Ajouter N exemples aléatoires (N > 1000), vérifier que len <= 1000
- [ ]* 13.3 Écrire test de propriété pour fine-tuning non-blocking
- **Property 6: Fine-tuning Non-blocking**
- **Validates: Requirements 5.1, 5.2**
- Lancer fine-tuning, vérifier que embed() continue de fonctionner
- [x] 14. Implémenter fine-tuning pour CLIPEmbedder
- Ajouter méthode `fine_tune()` à `CLIPEmbedder`
- Utiliser contrastive loss (positifs vs négatifs)
- Fine-tuner uniquement la dernière couche de projection
- Utiliser learning rate faible (1e-4)
- Limiter à 1 epoch pour rapidité
- Retourner métriques (loss, accuracy)
- _Requirements: 4.4, 5.2, 5.3, 7.2_
- [x] 15. Implémenter fine-tuning pour Pix2StructEmbedder
- Ajouter méthode `fine_tune()` à `Pix2StructEmbedder`
- Utiliser contrastive loss (positifs vs négatifs)
- Fine-tuner uniquement la dernière couche de l'encoder
- Utiliser learning rate faible (1e-4)
- Limiter à 1 epoch pour rapidité
- Retourner métriques (loss, accuracy)
- _Requirements: 4.4, 5.2, 5.3, 7.2_
- [x] 16. Intégrer fine-tuning dans Orchestrator
- Ajouter `LightweightFineTuner` à l'orchestrator
- Appeler `add_positive_example()` quand workflow accepté et réussi
- Appeler `add_negative_example()` quand workflow rejeté
- Sauvegarder checkpoint à l'arrêt
- Charger checkpoint au démarrage
- _Requirements: 4.1, 4.2, 5.5_
- [x] 17. Ajouter logging et métriques
- Logger le début/fin du fine-tuning
- Logger les métriques (loss, accuracy, durée)
- Logger le nombre d'exemples collectés
- Créer fichier de log dédié `fine_tuning.log`
- _Requirements: 7.2, 7.3_
- [x] 18. Checkpoint Final - Tester le système complet
- Lancer l'application en mode Assist
- Accepter plusieurs workflows → vérifier collection d'exemples positifs
- Rejeter plusieurs workflows → vérifier collection d'exemples négatifs
- Attendre le trigger (10 exemples) → vérifier que fine-tuning démarre
- Vérifier que l'application continue de fonctionner pendant le fine-tuning
- Vérifier que les métriques sont loggées
- Vérifier que le modèle s'améliore après fine-tuning
- Ensure all tests pass, ask the user if questions arise.
## Phase 4: Optimisations et Outils
- [x] 19. Optimiser les performances
- Implémenter batch processing pour embed_batch()
- Optimiser le cache (utiliser hash plus rapide si nécessaire)
- Profiler les performances (temps, mémoire)
- Ajuster les paramètres si nécessaire
- _Requirements: 6.3, 6.4, 6.5_
- [ ]* 19.1 Écrire tests de performance
- Mesurer temps d'embedding (GPU vs CPU)
- Mesurer temps de recherche FAISS
- Mesurer temps de fine-tuning
- Vérifier que les seuils sont respectés
- _Requirements: 6.5_
- [x] 20. Créer outils de visualisation
- Créer script `visualize_embeddings.py`
- Utiliser t-SNE ou UMAP pour visualiser les embeddings
- Afficher les clusters de workflows similaires
- Comparer CLIP vs Pix2Struct visuellement
- _Requirements: 7.5_
- [x] 21. Créer outils de debugging
- Créer script `debug_embeddings.py`
- Afficher les embeddings pour une image donnée
- Afficher les résultats de recherche FAISS
- Afficher l'historique de fine-tuning
- _Requirements: 7.4, 7.5_
- [x] 22. Documentation finale
- Documenter l'architecture dans README
- Documenter comment choisir entre CLIP et Pix2Struct
- Documenter le système de fine-tuning
- Créer guide de troubleshooting
- _Requirements: All_
## Phase 5: Intégration dans l'Orchestrator
- [x] 23. Intégrer le système d'embeddings dans l'Orchestrator
- Créer méthode `_init_new_embedding_system()`
- Initialiser EmbeddingManager, FAISSIndex, LightweightFineTuner
- Charger les checkpoints au démarrage
- Gérer les erreurs d'initialisation
- _Requirements: All_
- [x] 24. Implémenter l'indexation automatique des workflows
- Créer méthode `_index_workflow_in_faiss()`
- Convertir screenshots en embeddings
- Indexer dans FAISS avec metadata
- Logger les opérations
- _Requirements: 1.1, 1.2, 1.3_
- [x] 25. Implémenter la collection d'exemples pour fine-tuning
- Créer méthode `_add_positive_example_for_finetuning()`
- Créer méthode `_add_negative_example_for_finetuning()`
- Connecter aux callbacks de suggestions
- Gérer la conversion d'images
- _Requirements: 4.1, 4.2, 5.1_
- [x] 26. Implémenter la sauvegarde à l'arrêt
- Créer méthode `_save_embedding_system_on_shutdown()`
- Attendre la fin du fine-tuning en cours
- Sauvegarder l'index FAISS
- Sauvegarder le checkpoint du fine-tuner
- Logger les statistiques
- _Requirements: 1.3, 5.5_
- [x] 27. Créer tests d'intégration
- Test d'initialisation du système
- Test d'indexation de workflows
- Test de collection d'exemples positifs/négatifs
- Test du cache
- Test de sauvegarde/chargement
- _Requirements: All_
- [x] 28. Créer script de vérification
- Vérifier l'installation de FAISS
- Vérifier l'import des modules
- Lancer les tests d'intégration
- Vérifier les fichiers créés
- Vérifier la documentation
- _Requirements: All_
- [x] 29. Documentation de l'intégration
- Créer EMBEDDING_SYSTEM_INTEGRATED.md
- Documenter l'architecture complète
- Documenter l'utilisation
- Documenter le monitoring
- Créer guide de troubleshooting
- _Requirements: All_
## Statut Final
**INTÉGRATION COMPLÈTE**
Le système d'embeddings est maintenant complètement intégré dans GeniusIA v2 :
- ✅ Tous les composants sont implémentés
- ✅ Tous les tests passent
- ✅ La documentation est complète
- ✅ Le système est prêt pour la production
**Date de complétion** : 20 novembre 2024