IA locale pour PME suisse, guide décisionnel et procédures

Architectures IA locales pour PME suisses : RTX Spark, DGX Spark, RTX PRO 6000, H100. TCO réel, ingénierie RAG, conformité nLPD. Procédures opérationnelles publiées progressivement.

View the Project on GitHub doit4everyone/ia-locale-pme-suisse

§7 Pipelines n8n

Retour au sommaire Section précédente : §6 Cline : agent de codage Section suivante : §8 Fiabilité : hallucinations et contrôle d’ancrage

Statut : §7.1, §7.2 et §7.3 validés en lab sur VM-RAG-LAB, septembre 2026. Le résumé des réunions Teams (§7.4) est validé en Partie 3, voir §12. §7.5 (OCR factures) est documentaire : l’architecture est décrite mais non validée en lab, faute de GPU pour le modèle multimodal.


Ce que cette section documente : comment automatiser la synchronisation du corpus, la résolution des ACL NTFS et les notifications d’alerte via n8n. Trois pipelines sont validés en lab ici, un quatrième (Teams) en Partie 3. L’OCR des factures est documenté comme architecture de référence pour les déploiements avec GPU.


§7.1 Architecture générale

n8n orchestre trois catégories de tâches dans la stack RAG :

Catégorie Pipeline Déclencheur Statut
Maintenance Synchronisation corpus Schedule horaire Validé
Sécurité Rappel rotation svc-rag Schedule mensuel Validé
Productivité Résumé réunions Teams Schedule horaire Validé, voir §12
Productivité OCR et intégration factures Watch folder Documentaire

Les pipelines de maintenance et de sécurité sont indépendants du GPU. Le résumé Teams fonctionne sur CPU mais nécessite un tenant Microsoft 365 (§12). L’OCR des factures nécessite le GPU pour le modèle multimodal.

§7.1.1 Accès à l’interface n8n

n8n est accessible sur https://<RAG_FQDN>:5678 (par exemple https://rag.votre-domaine.ch:5678), à travers le frontal Nginx (§9.8).

Compte propriétaire. À la première ouverture, n8n affiche un écran d’inscription : le compte créé devient le propriétaire de l’instance. Le créer immédiatement après le déploiement, avec un mot de passe fort conservé dans le gestionnaire de mots de passe de l’organisation : tant qu’il n’existe pas, le premier venu qui ouvre l’adresse peut le créer. La double authentification est activée au niveau de l’instance par défaut (N8N_MFA_ENABLED, valeur par défaut true, d’après la documentation de n8n) ; l’activer pour le compte propriétaire est recommandé, non testé dans le lab.

Paquets communautaires (2.21.2). Le Compose fixe N8N_UNVERIFIED_PACKAGES_ENABLED=false : n8n n’installe aucun paquet communautaire non vérifié. n8n annonce ce réglage comme la future valeur par défaut ; les workflows du dépôt n’utilisent aucun paquet communautaire.

N8N_BASIC_AUTH_* retirées (2.21.1). Ces variables n’ont plus d’effet depuis n8n 1.0, qui a remplacé l’authentification basique par ses propres comptes. Elles figuraient encore dans le Compose et le .env du dépôt, et laissaient croire à une protection qu’elles n’apportaient pas. Sur une installation existante, les lignes restées dans le .env sont sans effet et peuvent être supprimées.

HTTPS depuis la 2.21.0 : n8n ne publie plus de port ; Nginx le sert en HTTPS sur le port 5678, sous le nom de la stack. Le Compose du dépôt lui indique qu’il est derrière un frontal (N8N_PROTOCOL=https, N8N_PROXY_HOPS=1, N8N_WEBHOOK_URL=https://<RAG_FQDN>:5678/) et réserve le cookie de session au HTTPS (N8N_SECURE_COOKIE=true). Avant la 2.21.0, l’accès se faisait en HTTP par http://<IP-VM>:5678, avec N8N_SECURE_COOKIE=false. Les workflows joignent toujours la RAG API par le réseau interne (http://rag-api:8080) : ils ne changent pas.

§7.1.2 Importer un pipeline

Dans n8n : Workflows → Import from file → sélectionner le fichier JSON. Après import, rattacher les credentials SMTP via le nœud email, puis cliquer sur Publish pour activer le Schedule.

Les deux workflows validés en lab sont publiés dans le dépôt :

Workflow Fichier JSON
Synchronisation corpus + email quarantaine n8n-sync-corpus.json
Rappel mensuel rotation svc-rag n8n-rappel-rotation-svc-rag.json

Avant import : remplacer les placeholders <EMAIL_EXPEDITEUR>, <EMAIL_DESTINATAIRE> et <ADMIN_TOKEN> par les valeurs réelles de l’environnement.

Credential SMTP obligatoire : les deux workflows utilisent un nœud email. Créer le credential dans n8n avant d’importer : Settings → Credentials → Add credential → SMTP. Renseigner le serveur, le port, l’utilisateur et le mot de passe. Après import du workflow, ouvrir le nœud email et sélectionner ce credential dans le champ “Credential”. Sans cette étape, le workflow s’exécute mais le nœud email échoue silencieusement.


§7.2 Pipeline 1 : synchronisation corpus

Ce pipeline ferme le point ouvert de §5 sur la cadence de resynchronisation des ACL. Il tourne toutes les heures et déclenche une notification email en cas d’erreur ou de fichiers en quarantaine.

§7.2.1 Architecture

Schedule Trigger (toutes les heures)
    ↓
POST http://rag-api:8080/admin/sync
    Authorization: Bearer <ADMIN_TOKEN>
    ↓
Réponse JSON :
    {success, quarantine_count, quarantine[], errors[],
     indexer: {returncode, stdout}, acl_resolver: {returncode, stdout}}
    ↓
IF success=false OR quarantine_count > 0
    ↓ oui                          ↓ non
Formater email              (rien, fin du pipeline)
    ↓
Send Email → <destinataire>

§7.2.2 Endpoint /admin/sync

L’endpoint est implémenté dans main.py de la RAG API. Il lance indexer.py puis acl_resolver.py en sous-processus et retourne un rapport JSON structuré.

Depuis la Partie 3 : une troisième étape, sp_indexer.py, s’ajoute si SP_SITES est renseigné (§13.6), et l’index BM25 est reconstruit après chaque synchronisation, même partiellement en échec. Le délai d’attente du nœud HTTP du workflow est porté à 30 minutes (1800000 ms), et celui de wget à 1800 secondes (-T 1800) pour un appel manuel.

# Extrait de main.py - endpoint /admin/sync
@app.post("/admin/sync")
async def admin_sync(
    credentials: HTTPAuthorizationCredentials = Security(security)
):
    if credentials.credentials != ADMIN_TOKEN:
        raise HTTPException(status_code=401, detail="Token admin invalide")
    # Lance indexer.py puis acl_resolver.py en sous-processus asyncio
    # Retourne {success, quarantine_count, quarantine[], errors[], ...}

Tester l’endpoint directement avant de construire le pipeline :

# Le port 8080 n'est pas publié sur le LAN (voir §3.4).
# Tester depuis le réseau Compose via le conteneur n8n.
# Le token est lu depuis le .env : ni copié à la main, ni conservé
# dans l'historique du shell. --post-data est obligatoire : /admin/sync
# n'accepte que POST, sans cette option wget envoie un GET (réponse 405).
cd /root/rag-stack
TOKEN=$(grep '^ADMIN_TOKEN=' .env | cut -d= -f2-)
docker compose exec n8n wget -qO- --post-data='' \
  --header="Authorization: Bearer $TOKEN" \
  http://rag-api:8080/admin/sync | python3 -m json.tool
unset TOKEN

Résultat attendu en fonctionnement normal :

{
    "timestamp": "2026-09-24T14:59:49.859944+00:00",
    "indexer": {"returncode": 0},
    "acl_resolver": {"returncode": 0},
    "quarantine": [],
    "errors": [],
    "success": true,
    "quarantine_count": 0
}

§7.2.3 Variables requises

Dans /root/rag-stack/.env, ajouter :

# Synchronisation corpus
ADMIN_TOKEN=<token-admin-fort>
SYNC_SCRIPTS_DIR=/rag-pipeline
SMB_SHARE=//<NOM-FILESERVER>/FileService
SMB_MOUNT=/mnt/corpus-root
SMB_USER=svc-rag
SMB_PASSWORD=<mot-de-passe-svc-rag>
SMB_DOMAIN=DOMAINE

Sécurité de l’endpoint /admin/sync :

Injection de commande : tous les paramètres transmis aux sous-processus (chemins, partage SMB, credentials) viennent exclusivement du fichier .env, jamais du corps de la requête HTTP. Un appelant ne peut pas modifier les arguments passés aux scripts.

Chevauchement de synchronisations : un verrou global (asyncio.Lock) empêche deux synchronisations simultanées. Si une passe est déjà en cours, l’endpoint retourne HTTP 409. Sans ce verrou, deux appels simultanés (Schedule + appel manuel) pourraient corrompre les métadonnées Qdrant en écrivant les mêmes chunks en parallèle.

Exposition réseau : le port 8080 n’est pas publié sur le LAN depuis la v2.4.0 (voir §3.4). docker-compose.yml ne comporte plus de section ports pour rag-api. Open WebUI et n8n joignent la RAG API via http://rag-api:8080 sur le réseau Compose interne. Ne jamais publier ce port sur internet.

ADMIN_TOKEN distinct de API_TOKEN : un token séparé permet de révoquer l’accès admin sans impacter les utilisateurs de la RAG API.

§7.2.4 Dockerfile et volumes

Cette section est remplacée par §3.3 et §3.4. Le Dockerfile, requirements.txt et les volumes de rag-api sont documentés et maintenus dans la section §3. Les rapports JSON sont écrits dans /var/log/rag/ (monté en écriture), et /rag-pipeline est monté en lecture seule (:ro). Voir §3.4 pour la configuration complète.

§7.2.5 Fenêtre de péremption des ACL

Entre deux passes du résolveur, un droit révoqué dans AD reste actif dans Qdrant. Avec une cadence horaire, la fenêtre maximale est d’une heure.

Événement Délai avant prise en compte
Nouveau fichier déposé 0 à 60 minutes
Fichier modifié 0 à 60 minutes (hash SHA-256 tronqué détecte le changement)
Fichier inchangé Aucun traitement : l’indexeur compare le hash et saute le fichier
Permission révoquée 0 à 60 minutes
Permission accordée 0 à 60 minutes

La cadence est configurable en modifiant l’expression cron dans le Schedule Trigger. Pour une organisation avec des révocations fréquentes, passer à 15 minutes.

§7.2.6 Nœud IF : conditions de déclenchement

Le nœud IF déclenche l’email si l’une des deux conditions est vraie :

Condition Signification
`` equals false Un des deux scripts a retourné une erreur
`` greater than 0 Des fichiers sont présents sur le partage mais absents de Qdrant

En fonctionnement normal, le pipeline se termine silencieusement sans envoyer d’email. Une notification signale toujours une action requise.

§7.2.7 Format des emails de notification

Email d’erreur :

RAPPORT DE SYNCHRONISATION RAG : ERREUR
Horodatage : 11.09.2026 10:08:48

Erreurs détectées :
  • indexer.py a retourné code 1

Codes de retour : indexer.py = 1, acl_resolver.py = 0

Détail sur VM-RAG-LAB :
  docker logs rag-api 2>&1 | grep SYNC | tail -20
  ls -la /var/log/rag/rapport_*.json

Où trouver le détail d’une erreur : l’endpoint /admin/sync ne renvoie que les codes de retour des deux scripts, pas leur sortie. Le détail est dans les logs du conteneur ([SYNC], avec la fin de la sortie d’erreur du script en échec) et dans les rapports JSON écrits dans /var/log/rag/. L’email indique où chercher.

Email de quarantaine :

RAPPORT DE SYNCHRONISATION RAG : QUARANTAINE
Horodatage : 11.09.2026 10:08:48
Synchronisation : succès

3 fichier(s) en quarantaine :
  • CLIENTS/ClientX/nouveau-contrat.docx
  • RH/POLITIQUE RH/reglement-2027.docx
  • ...

Ces fichiers sont présents sur le partage mais non indexés.
Action requise : vérifier le contenu et relancer l'indexation manuellement si nécessaire.

§7.2.8 Validation en lab

Résultats obtenus sur le corpus Axonix SA (12 documents, 68 chunks) :

Exécution manuelle du workflow : success=true
indexer.py     : returncode 0, 68 chunks indexés
acl_resolver.py: returncode 0, 68 chunks mis à jour
quarantine_count: 0
Email reçu     : non (pas d'erreur, pas de quarantaine)

Test de déclenchement email (condition IF forcée à true) : email reçu sur <destinataire> avec le rapport correct.

Fichier importable : n8n-sync-corpus.json


§7.3 Pipeline 2 : rappel mensuel de rotation du compte svc-rag

Ce pipeline envoie automatiquement la procédure de rotation du mot de passe de svc-rag le 1er de chaque mois. Il évite qu’une rotation soit oubliée et fournit les commandes exactes dans l’email.

§7.3.1 Architecture

Schedule Trigger (1er du mois, 09h00)
    ↓
Code JS (formater le rappel avec date et procédure)
    ↓
Send Email → <destinataire>

§7.3.2 Procédure incluse dans l’email

L’email contient la procédure complète en 7 étapes dans l’ordre exact à suivre :

  1. Générer un nouveau mot de passe fort
  2. Changer dans Active Directory via Set-ADAccountPassword
  3. Mettre à jour /etc/smbcredentials/svc-rag sur VM-RAG-LAB
  4. Mettre à jour LDAP_BIND_PWD et SMB_PASSWORD dans .env
  5. Redémarrer la RAG API : docker compose up -d rag-api
  6. Vérifier via POST /admin/sync : success: true (commande en §9.5.1)
  7. Tester l’authentification LDAP dans Open WebUI

Pourquoi l’ordre est critique : si l’étape 2 (AD) est faite avant l’étape 3 (fichier credentials), le montage SMB tombe immédiatement. Si l’étape 5 (restart) est oubliée, la RAG API continue d’utiliser l’ancien mot de passe pour LDAP et les requêtes tombent silencieusement sans message d’erreur visible pour l’utilisateur.

§7.3.3 Expression cron

0 9 1 * *

Heure suisse : vérifier que le conteneur n8n est en UTC et que 09h00 CET/CEST correspond à 08h00 ou 07h00 UTC selon la saison. Adapter l’expression cron en conséquence :

Saison Heure suisse Expression cron (UTC)
Hiver (CET, UTC+1) 09h00 0 8 1 * *
Été (CEST, UTC+2) 09h00 0 7 1 * *

Pour éviter ce problème, définir TZ=Europe/Zurich dans les variables d’environnement du conteneur n8n.

§7.3.4 Validation en lab

Email reçu avec la procédure complète en 7 étapes. Sujet : [RAG Stack] Rappel : rotation du mot de passe svc-rag : septembre 2026.

Fichier importable : n8n-rappel-rotation-svc-rag.json


§7.4 Pipeline 3 : résumé de réunions Teams

Ce pipeline est documenté et validé en lab dans la Partie 3 : §12 Synthèse des réunions Teams.

L’architecture retenue diffère de celle esquissée dans les premières versions de ce guide : le compte rendu n’est pas déposé dans un canal Teams, mais envoyé en brouillon à l’organisateur seul, qui relit et décide de la diffusion. La synthèse est faite par la RAG API (/teams/sync), n8n se charge de la planification et de l’envoi.


§7.5 Pipeline 4 : OCR et intégration de factures (documentaire)

Statut documentaire : ce pipeline nécessite Qwen2-VL 7B (modèle multimodal) et sera validé lors de l’installation du GPU RTX 5060 Ti. Il sera documenté dans §10 avec les mesures de performance réelles.

Ce pipeline surveille un dossier de réception de factures, extrait les données structurées via le modèle multimodal et les envoie à l’ERP.

§7.5.1 Architecture du pipeline

Watch Folder → /mnt/corpus-root/FACTURES/entrant (polling 5 min)
    ↓
HTTP Request → POST vLLM /v1/chat/completions
    Model: Qwen2-VL-7B (multimodal)
    Message: image PDF + prompt extraction JSON
    ↓
Code Node → validation et mapping vers format ERP
    ↓
HTTP Request → POST endpoint ERP (API Abacus ou équivalent)
    ↓
IF anomalie détectée
    ↓
Email → notification validation manuelle requise

§7.5.2 Prompt d’extraction

Tu reçois l'image d'une facture. Extrais les données suivantes
au format JSON strict, sans commentaire :
{
  "fournisseur": "...",
  "numero_facture": "...",
  "date_facture": "JJ.MM.AAAA",
  "montant_ht": 0.00,
  "montant_tva": 0.00,
  "montant_ttc": 0.00,
  "devise": "CHF",
  "iban": "...",
  "lignes": [
    {"description": "...", "quantite": 0, "prix_unitaire": 0.00}
  ]
}
Si un champ est absent de la facture, mettre null.

Fiabilité : 85 à 95% sur un corpus de factures homogènes, selon des déploiements documentés publiquement (chiffre repris du guide décisionnel §2.1, non mesuré sur ce lab). Les cas ambigus sont signalés pour validation manuelle. La vérification humaine reste recommandée avant envoi à l’ERP.


§7.6 Configuration SMTP

Les pipelines §7.2 et §7.3 utilisent le même credential SMTP. Le nœud email n8n supporte STARTTLS sur le port 587 (Office 365).

Paramètre Valeur
Host smtp.office365.com
Port 587
SSL/TLS Désactivé (STARTTLS sur 587)
User <compte-envoi>@votre-domaine.ch
Password Mot de passe d’application

Dépréciation SMTP AUTH : Microsoft supprime progressivement SMTP AUTH et les mots de passe d’application sur Exchange Online. La date de suppression définitive n’est pas encore annoncée officiellement, mais la migration vers OAuth2 + Graph API est à planifier. Le nœud n8n “Microsoft Outlook” ou un HTTP Request vers https://graph.microsoft.com/v1.0/me/sendMail avec un token OAuth2 est la solution de remplacement. Cette migration sera documentée en Partie 3 avec les connecteurs Microsoft 365.


Retour au sommaire Section précédente : §6 Cline : agent de codage Section suivante : §8 Fiabilité : hallucinations et contrôle d’ancrage

§7.1, §7.2 et §7.3 validés en lab sur VM-RAG-LAB, septembre 2026. §7.4 et §7.5 sont des architectures de référence non validées en lab.