← The Forge
Recettes 6 juin 2026 · 6 · par L'équipe WORKFLOW v6

Recette : Mettre en place un pipeline d’adversarial testing avec Workflow v6

Découvrez comment construire, automatiser et monitorer un pipeline d’évaluation de robustesse adversariale pour vos modèles IA à l’aide de Workflow v6, de la génération d’attaques à la production de rapports détaillés.

Contexte et objectifs

Les modèles d’apprentissage profond sont de plus en plus déployés en production, mais leur vulnérabilité aux perturbations adversariales (ex. images légèrement modifiées, texte reformulé) reste un risque majeur. Un pipeline d’adversarial testing permet de détecter ces faiblesses de façon systématique, d‑enrichir les jeux de données d’entraînement et d‑informer les équipes produit. Workflow v6 offre les primitives nécessaires : orchestration de tâches, gestion des artefacts, et intégration native aux systèmes CI/CD.

L’objectif de cette recette :

  • Générer automatiquement des exemples adversariaux à partir d’un modèle entraîné.
  • Évaluer la perte de performance (accuracy, F1, etc.) sur ces exemples.
  • Produire un rapport exploitable (HTML/JSON) et le publier comme artefact de build.
  • Enclencher une étape de « re‑training » conditionnelle si la dégradation dépasse un seuil défini.

Définir le pipeline d’adversarial testing dans Workflow v6

1. Déclaration du workflow

name: adversarial-testing
on:
  push:
    branches: [main]
  schedule:
    - cron: "0 2 * * MON"   # chaque lundi à 02:00
jobs:
  generate_attacks:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install torch torchvision foolbox==3.3.0
      - name: Pull trained model
        uses: workflow-v6/artifact@v1
        with:
          name: model.pt
          path: artifacts/model.pt
      - name: Generate adversarial samples
        id: attacks
        run: |
          python scripts/generate_attacks.py \
            --model artifacts/model.pt \
            --output attacks.npy
      - name: Upload attacks
        uses: workflow-v6/artifact@v1
        with:
          name: attacks
          path: attacks.npy
  evaluate:
    needs: generate_attacks
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Install evaluation deps
        run: |
          pip install torch torchvision foolbox==3.3.0 pandas
      - name: Download artifacts
        uses: workflow-v6/artifact@v1
        with:
          name: model.pt
          path: model.pt
      - name: Download attacks
        uses: workflow-v6/artifact@v1
        with:
          name: attacks
          path: attacks.npy
      - name: Run evaluation
        id: eval
        run: |
          python scripts/evaluate_attacks.py \
            --model model.pt \
            --attacks attacks.npy \
            --report report.json
      - name: Publish report
        uses: workflow-v6/artifact@v1
        with:
          name: adversarial-report
          path: report.json

Ce fichier décrit deux jobs : generate_attacks crée les exemples adversariaux à l’aide de Foolbox, puis les stocke comme artefact; evaluate charge le modèle et les attaques, calcule les métriques de robustesse et génère un rapport JSON.

2. Script de génération d’attaques (generate_attacks.py)

import argparse
import numpy as np
import torch
import foolbox as fb
from torchvision import models, transforms

parser = argparse.ArgumentParser()
parser.add_argument('--model', required=True)
parser.add_argument('--output', required=True)
args = parser.parse_args()

# Chargement du modèle PyTorch
model = torch.load(args.model)
model.eval()

# Wrapper Foolbox
fmodel = fb.PyTorchModel(model, bounds=(0, 1))

# Exemple de jeu de données (CIFAR‑10) – ici on charge juste 100 images aléatoires
transform = transforms.Compose([transforms.ToTensor()])
images = torch.randn(100, 3, 32, 32)  # placeholder, remplacer par un vrai DataLoader
labels = torch.randint(0, 10, (100,))

# Attaque FGSM (Fast Gradient Sign Method)
adversarial = []
for img, lbl in zip(images, labels):
    raw, clipped, is_adv = fb.attacks.FGSM()(fmodel, img.unsqueeze(0), lbl)
    adversarial.append(clipped.squeeze(0).numpy())

np.save(args.output, np.stack(adversarial))

Le script reste générique : il suffit de remplacer le jeu de données factice par un DataLoader réel. D’autres attaques (PGD, DeepFool) peuvent être sélectionnées en changeant la classe fb.attacks.XYZ.

3. Script d’évaluation (evaluate_attacks.py)

import argparse, json, numpy as np, torch
from torch.utils.data import TensorDataset, DataLoader
import foolbox as fb

parser = argparse.ArgumentParser()
parser.add_argument('--model', required=True)
parser.add_argument('--attacks', required=True)
parser.add_argument('--report', required=True)
args = parser.parse_args()

model = torch.load(args.model)
model.eval()
fmodel = fb.PyTorchModel(model, bounds=(0, 1))

adv_images = np.load(args.attacks)
# Supposons que les labels originaux soient connus et stockés séparément
# Ici on génère des labels aléatoires comme placeholder
labels = torch.randint(0, 10, (adv_images.shape[0],))

dataset = TensorDataset(torch.tensor(adv_images, dtype=torch.float32), labels)
loader = DataLoader(dataset, batch_size=32)

correct = 0
total = 0
for imgs, lbls in loader:
    preds = model(imgs).argmax(dim=1)
    correct += (preds == lbls).sum().item()
    total += lbls.size(0)

accuracy_adv = correct / total
report = {
    "adversarial_accuracy": accuracy_adv,
    "total_samples": total,
    "threshold": 0.70  # valeur de référence, configurable
}

with open(args.report, 'w') as f:
    json.dump(report, f, indent=2)

Le rapport JSON contient la accuracy sur les exemples adversariaux ainsi qu’un seuil de tolérance configurable.

Intégration au CI/CD et automatisation des rapports

  1. Publication du rapport – Workflow v6 expose les artefacts via son UI ; on peut également pousser le JSON vers un tableau de bord interne (Grafana, Kibana) à l’aide d’un webhook.
  2. Gate de qualité – Ajoutez une étape conditionnelle qui arrête le pipeline si adversarial_accuracy < threshold :
  - name: Check robustness
    if: steps.eval.outputs.adversarial_accuracy < 0.70
    run: |
      echo "Robustness below threshold – aborting deploy"
      exit 1
  1. Re‑training automatisé – Si le test échoue, déclenchez un job retrain qui ré‑entraîne le modèle avec les exemples adversariaux ajoutés au jeu d’entraînement.
  2. Alerting – Configurez un alert dans votre système de monitoring (ex. PagerDuty) en s’appuyant sur l’événement workflow-v6:artifact:adversarial-report.

Bonnes pratiques et points de vigilance

  • Sélection du jeu d’échantillons : testez sur un sous‑ensemble représentatif (au moins 5 % du jeu de validation) pour limiter le temps d’exécution.
  • Diversité des attaques : ne vous limitez pas à FGSM. Combinez méthodes gradient‑based et optimisation‑based pour couvrir différents vecteurs d’attaque.
  • Gestion des ressources : les attaques PGD sont coûteuses en GPU. Utilisez les options --batch-size et --max-steps pour éviter la saturation du runner.
  • Versionnage des modèles : chaque exécution doit référencer une version de modèle immuable (hash Git ou tag Docker) afin de garantir la traçabilité.
  • Sécurité des artefacts : les exemples adversariaux peuvent contenir des informations sensibles (images réelles). Appliquez le chiffrement fourni par Workflow v6 avant le stockage.

En suivant cette recette, les équipes produit gagnent en visibilité sur la robustesse de leurs modèles, intègrent la détection de vulnérabilités dès le commit, et automatisent la réponse (re‑training, notification). Workflow v6 assure la cohérence du processus tout en restant agnostique quant aux bibliothèques d’attaque utilisées.

Envie d’aller plus loin avec WORKFLOW v6 ?

Découvrir WORKFLOW v6