Nodes n8n pour remplir automatiquement des documents DOCX avec des tags {{TAG}}.
Parfait pour: Contrats, factures, devis, formulaires, lettres, ou tout document avec des champs a remplir.
| Node | Role | LLM requis |
|---|---|---|
| Template Mapper | Analyse un document vierge et insere les tags {{TAG}} via IA |
Oui |
| DOCX Template Filler | Remplit les tags avec les valeurs JSON | Non |
# Dans votre installation n8n
npm install n8n-nodes-docx-filler
# Ou en mode developpement
cd ~/.n8n/custom
git clone https://github.com/rokodo-io/n8n-nodes-docx-filler
cd n8n-nodes-docx-filler
npm install && npm run build
# Redemarrer n8nETAPE 1: Creer le template (une seule fois par type de document)
Document vierge ββββββ
(ex: contrat.docx) β
ββββΊ Template Mapper βββΊ Template avec {{TAGS}}
Structure JSON βββββββ + LLM + dataStructure exacte
(champs a remplir)
ETAPE 2: Remplir le template (a chaque utilisation)
Template avec tags ββββββ
(ex: contrat_TEMPLATE) β
ββββΊ DOCX Template Filler βββΊ Document rempli
Donnees JSON ββββββββββββ
(valeurs reelles)
Analyse un document vierge et une structure JSON, puis utilise l'IA pour placer les tags {{TAG}} aux bons emplacements.
| Parametre | Description |
|---|---|
| Document Vierge | Propriete binaire contenant le DOCX a analyser |
| Structure de Donnees | JSON decrivant les champs a placer |
| LLM (requis) | Modele IA pour deduire les emplacements |
| Option | Description |
|---|---|
| Seuil de Confiance | Score minimum (0-100) pour inserer un tag |
| Nom Fichier Sortie | Nom du template genere |
| Inclure Details | Affiche les scores de confiance (debug) |
Entree:
{
"client": {
"nom": "",
"email": "",
"telephone": ""
},
"commande": {
"numero": "",
"date": "",
"montant": ""
}
}Sortie:
- Document DOCX avec tags:
{{CLIENT_NOM}},{{CLIENT_EMAIL}},{{COMMANDE_NUMERO}}, etc. dataStructurepour DocxTemplateFiller:
{
"dataStructure": {
"CLIENT_NOM": "",
"CLIENT_EMAIL": "",
"CLIENT_TELEPHONE": "",
"COMMANDE_NUMERO": "",
"COMMANDE_DATE": "",
"COMMANDE_MONTANT": ""
}
}Remplit un document DOCX contenant des tags {{TAG}} avec des donnees JSON.
| Parametre | Description |
|---|---|
| Document Template | Propriete binaire contenant le DOCX avec tags |
| Source des Donnees | JSON complet ou champ specifique |
| Option | Description |
|---|---|
| Style Checkboxes | Unicode, Texte (X), ou Boolean |
| Nom Fichier Sortie | Nom du document genere |
| Conserver Tags Vides | Garder les {{TAG}} sans valeur |
| Rapport de Mapping | Liste des tags remplaces/restants |
Entree:
{
"client": {
"nom": "Marie Dupont",
"email": "marie@example.com",
"telephone": "+33 6 12 34 56 78"
},
"commande": {
"numero": "CMD-2024-001",
"date": "30/12/2024",
"montant": "1 250,00 EUR"
}
}Sortie:
- Document DOCX avec les valeurs inserees
- Rapport:
{
"success": true,
"report": {
"tagsReplaced": 6,
"tagsRemaining": 0,
"replacedTags": ["CLIENT_NOM", "CLIENT_EMAIL", "CLIENT_TELEPHONE", "COMMANDE_NUMERO", "COMMANDE_DATE", "COMMANDE_MONTANT"]
}
}Les cles JSON sont automatiquement converties en tags majuscules:
| Structure JSON | Tag genere |
|---|---|
client.nom |
{{CLIENT_NOM}} |
client.email |
{{CLIENT_EMAIL}} |
adresse.rue |
{{ADRESSE_RUE}} |
produit.prix_unitaire |
{{PRODUIT_PRIX_UNITAIRE}} |
date_livraison |
{{DATE_LIVRAISON}} |
Les booleens sont automatiquement convertis en checkboxes:
| JSON | Resultat (Unicode) | Resultat (Texte) |
|---|---|---|
true |
β | X |
false |
β | (espace) |
{
"societe": {
"nom": "",
"adresse": "",
"siret": ""
},
"client": {
"nom": "",
"prenom": "",
"email": "",
"adresse": ""
},
"devis": {
"numero": "",
"date": "",
"validite": "",
"montant_ht": "",
"tva": "",
"montant_ttc": ""
},
"conditions": {
"paiement_30j": false,
"paiement_comptant": false,
"livraison_incluse": false
},
"signature": {
"lieu": "",
"date": ""
}
}{{SOCIETE_NOM}}, {{SOCIETE_ADRESSE}}, {{SOCIETE_SIRET}}
{{CLIENT_NOM}}, {{CLIENT_PRENOM}}, {{CLIENT_EMAIL}}, {{CLIENT_ADRESSE}}
{{DEVIS_NUMERO}}, {{DEVIS_DATE}}, {{DEVIS_VALIDITE}}
{{DEVIS_MONTANT_HT}}, {{DEVIS_TVA}}, {{DEVIS_MONTANT_TTC}}
{{CONDITIONS_PAIEMENT_30J}}, {{CONDITIONS_PAIEMENT_COMPTANT}}, {{CONDITIONS_LIVRAISON_INCLUSE}}
{{SIGNATURE_LIEU}}, {{SIGNATURE_DATE}}
{
"societe": {
"nom": "TechCorp SAS",
"adresse": "45 avenue des Champs, 75008 Paris",
"siret": "123 456 789 00012"
},
"client": {
"nom": "Martin",
"prenom": "Jean",
"email": "jean.martin@email.com",
"adresse": "12 rue de la Paix, 69001 Lyon"
},
"devis": {
"numero": "DEV-2024-0042",
"date": "30/12/2024",
"validite": "30 jours",
"montant_ht": "5 000,00",
"tva": "1 000,00",
"montant_ttc": "6 000,00"
},
"conditions": {
"paiement_30j": true,
"paiement_comptant": false,
"livraison_incluse": true
},
"signature": {
"lieu": "Paris",
"date": "30/12/2024"
}
}Template Mapper fonctionne avec tous les LLM de n8n:
- OpenAI (GPT-4, GPT-4o, GPT-3.5)
- Anthropic (Claude 3, Claude 3.5)
- Ollama (Llama, Mistral, Qwen - local et gratuit)
- Azure OpenAI
- Google Gemini
- Mistral AI
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β TEMPLATE MAPPER β
β (Utilise l'IA - Transfer Learning) β
β β
β Document Cible (sans tags) βββ β
β ββββΊ Segmentation βββΊ Prompts LLM βββΊ Tags β
β Template Reference (avec tags) ββ par section par segment inseres β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β DOCX TEMPLATE FILLER β
β (PAS d'IA - Remplacement direct) β
β β
β Document avec {{TAGS}} βββ β
β ββββΊ Flatten JSON βββΊ Replace Tags βββΊ Document β
β Donnees JSON βββββββββββββ CLIENT_NOM {{TAG}}βvaleur rempli β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Le Template Mapper utilise un systeme de segmentation pour ameliorer la precision du matching IA. Voici comment ca fonctionne:
Sans segmentation, le LLM recoit tout le document en une seule fois:
- Prompts trop volumineux: Risque d'erreur HTTP 413 (Request Entity Too Large)
- Confusions entre sections: L'IA peut confondre des sections similaires (ex: plusieurs tableaux)
- Moins de precision: Plus le contexte est grand, moins l'IA est precise
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β FLUX DE SEGMENTATION β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β 1. SEGMENTER les documents β
β Template: [Section A] [Tableau CA] [Section B] [Signature] β
β Cible: [Section A'] [Tableau CA'] [Section B'] [Signature'] β
β β
β 2. MATCHER les segments (template β cible) β
β Section A ββ Section A' (score: 85%) β
β Tableau CA ββ Tableau CA' (score: 92%) β
β etc. β
β β
β 3. GENERER un prompt CIBLE par paire de segments β
β Prompt segment CA: "Tu as les tags CA_N, CA_N1... dans ce tableau" β
β β L'IA ne traite QUE ce segment, pas tout le document β
β β
β 4. COMBINER les resultats de tous les segments β
β Matches totaux = Matches(A) + Matches(CA) + Matches(B) + ... β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
| Mode | Comportement |
|---|---|
| auto (defaut) | Active la segmentation si: document > 50KB OU > 10 tags OU tags repartis sur 3+ sections |
| always | Force la segmentation. Recommande pour les tableaux financiers (CA) |
| never | Desactive la segmentation. Utilise le prompt global |
// Dans TemplateMapper.node.ts ligne 352-356
const useSegmentation = decideSegmentationMode(
params.useSegmentation, // 'auto' | 'always' | 'never'
templateXml,
extractedTags
);Le systeme utilise maintenant une approche Few-Shot Learning pour que l'IA "consomme" vraiment la logique:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β AVANT vs APRES β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β AVANT (regles abstraites): β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β "REGLE 1: Les tags d'identification doivent etre places β β
β β APRES le label correspondant..." β β
β β β L'IA IGNORE souvent ces regles β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β APRES (exemples concrets): β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β "### Tag: {{NOM_COMMERCIAL}} β β
β β - Contexte template: 'Nom commercial :' β β
β β - Candidat cible: idx=15 ('Nom commercial :...')" β β
β β β L'IA COMPREND par l'exemple β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- Montrer, pas expliquer: Chaque tag est presente avec son contexte reel
- Pre-calcul des candidats: Le systeme trouve les candidats probables AVANT d'appeler l'IA
- Format JSON strict: L'IA voit le format exact attendu dans le prompt
- Validation robuste: Parsing multi-strategies avec logs detailles
| Fichier | Changement |
|---|---|
prompt.service.ts |
Nouvelle fonction buildFewShotExamples() |
segment-matcher.service.ts |
Prompt Few-Shot par segment |
llm.service.ts |
Parsing robuste avec logs detailles |
Il y a plusieurs raisons pour lesquelles le LLM peut ne pas retourner de matches valides:
// Dans llm.service.ts ligne 128-139
return parsed.matches.filter((match) => {
return (
match.confidence >= 0.7 && // β Confiance trop basse
match.tag && // β Tag absent
(match.targetParagraphIndex !== undefined || match.targetIdx !== undefined)
);
});Cause: L'IA retourne des matches avec confidence < 0.7 β ils sont filtres.
// Dans llm.service.ts ligne 149-153
} catch {
// En cas d'erreur de parsing, retourner une liste vide
return [];
}Cause: Le LLM retourne du texte non-JSON ou du JSON mal forme.
// Dans TemplateMapper.node.ts ligne 424-435
if (matches.length === 0) {
console.log('β οΈ LLM n\'a retourne aucun match, fallback vers matching par patterns...');
matches = patternBasedMatching(tagContexts, targetParagraphs);
patternFallbackUsed = true;
}Cause: Si l'IA echoue, le systeme utilise un matching par patterns (regex/similarite textuelle) comme secours.
// Dans prompt.service.ts lignes 46-48
const MAX_PROMPT_SIZE = 60000; // 60KB max
const MAX_PARAGRAPHS = 80; // Max paragraphes envoyes au LLM
const MAX_TAG_CONTEXTS = 40; // Max contextes de tagsCause: Si le document depasse ces limites, des informations sont tronquees et l'IA peut manquer des correspondances.
| Modele | Precision attendue | Recommandation |
|---|---|---|
| GPT-4, GPT-4o | Haute | Recommande |
| Claude 3.5 Sonnet, Opus | Haute | Recommande |
| Gemini Pro | Moyenne-Haute | OK |
| Mistral Large | Moyenne | OK pour documents simples |
| Ollama (local) | Variable | Depend du modele |
| GPT-3.5 | Basse | Non recommande |
1. Charger les documents
βββ Document cible (binaire β XML)
βββ Template reference (binaire β XML)
2. Extraire les tags du template
βββ Regex: /\{\{([A-Z][A-Z0-9_]*)\}\}/g
3. Extraire les contextes (labelBefore, section, type)
βββ Pour chaque tag: quel texte le precede?
4. DECISION: Segmentation ou Global?
βββ Si 'always' ou criteres auto remplis β MODE SEGMENTE
β βββ Segmenter template et cible
β βββ Matcher les segments
β βββ Pour chaque paire:
β β βββ Generer prompt cible
β β βββ Appeler LLM
β β βββ Parser reponse
β βββ Combiner resultats
β
βββ Sinon β MODE GLOBAL
βββ Generer prompt unique (tout le document)
βββ Appeler LLM
βββ Parser reponse
5. FALLBACK si aucun match
βββ patternBasedMatching (regex + similarite)
6. Appliquer les tags au document cible
βββ Pour chaque match:
β βββ Trouver le paragraphe XML
β βββ Inserer {{TAG}} selon insertionPoint
β βββ Valider le XML
βββ Generer le document final
7. Retourner
βββ Document DOCX tagge (binaire)
βββ dataStructure (JSON pour DocxTemplateFiller)
βββ Statistiques (tags appliques, echecs)
| Type | Description | Exemple |
|---|---|---|
| after_colon | Apres un label finissant par ":" | Nom commercial : β Nom commercial : {{NOM}} |
| table_cell | Dans une cellule de tableau | Cellule vide β {{CA_N}} |
| replace_empty | Remplace un paragraphe vide | <w:p/> β <w:p>{{TAG}}</w:p> |
| inline | Dans le texte existant | Le montant est X β Le montant est {{MONTANT}} |
| checkbox | Case a cocher | β β β ou β selon valeur |
Le systeme detecte et mappe automatiquement les cases a cocher entre le template et le document cible.
| Format | Detection | Exemple |
|---|---|---|
| Unicode | β β β‘ β β | β Oui β Non |
| Word Form Controls | FORMCHECKBOX | Controles de formulaire Word |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β MAPPING DES CHECKBOXES β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β TEMPLATE CIBLE β
β βββββββββββββββββββββββ βββββββββββββββββββββββ β
β β β Candidat seul β β β FORMCHECKBOX seul β β
β β β Groupement β β β FORMCHECKBOX group. β β
β β β Oui β Non β β β FORMCHECKBOX Oui/Nonβ β
β βββββββββββββββββββββββ βββββββββββββββββββββββ β
β β
β Le systeme: β
β 1. Detecte les checkboxes dans les deux documents β
β 2. Extrait leur etat (coche/non coche) β
β 3. Trouve les correspondances par similarite semantique β
β 4. Genere des tags booleens β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Les checkboxes sont incluses dans la sortie:
{
"checkboxes": {
"templateCount": 7,
"targetCount": 7,
"pairsDetected": 1,
"tags": {
"LE_CANDIDAT_SE_PRESENTE_SEUL": false,
"GROUPEMENT_CONJOINT": true,
"QUESTION_OUI_NON": false
}
}
}Le systeme detecte automatiquement les paires de checkboxes Oui/Non:
Template: β Oui β Non β Tag: {{QUESTION}} = false
Template: β Oui β Non β Tag: {{QUESTION}} = true
- Format attendu:
{{TAG_NAME}}(double accolades, majuscules, underscores) - Verifiez que les cles JSON correspondent aux tags du document
- Utilisez le rapport de mapping pour voir les tags restants
- Baissez le seuil de confiance (par defaut: 70)
- Verifiez que les noms de champs sont semantiquement clairs
- Activez "Inclure Details" pour voir les scores de confiance
- Verifiez que les fichiers source sont des DOCX valides
- N'utilisez pas de fichiers DOC (ancien format)
- Les caracteres
<,>,&sont automatiquement echappes - Les accents et emojis sont supportes
MIT - Rokodo.io