334 lines
8.3 KiB
JSON
334 lines
8.3 KiB
JSON
{
|
|||
|
|
"name": "78 FAQ import + gate (reference)",
|
||
|
|
"nodes": [
|
||
|
|
{
|
||
|
|
"name": "Import webhook",
|
||
|
|
"type": "n8n-nodes-base.webhook",
|
||
|
|
"typeVersion": 2,
|
||
|
|
"parameters": {
|
||
|
|
"httpMethod": "POST",
|
||
|
|
"path": "my-faq-import",
|
||
|
|
"responseMode": "responseNode",
|
||
|
|
"options": {}
|
||
|
|
},
|
||
|
|
"position": [
|
||
|
|
0,
|
||
|
|
300
|
||
|
|
],
|
||
|
|
"id": "a56860cf-55b7-5565-b18d-ca3e5e9abe79",
|
||
|
|
"webhookId": "f3d72461-ee99-519a-a141-33709a703108"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"name": "Run check",
|
||
|
|
"type": "n8n-nodes-base.httpRequest",
|
||
|
|
"typeVersion": 4.2,
|
||
|
|
"parameters": {
|
||
|
|
"url": "http://localhost:5678/webhook/my-faq-check",
|
||
|
|
"options": {
|
||
|
|
"response": {
|
||
|
|
"response": {
|
||
|
|
"neverError": true
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"timeout": 30000
|
||
|
|
},
|
||
|
|
"method": "POST",
|
||
|
|
"sendBody": true,
|
||
|
|
"specifyBody": "json",
|
||
|
|
"jsonBody": "={{ JSON.stringify($json.body) }}"
|
||
|
|
},
|
||
|
|
"position": [
|
||
|
|
220,
|
||
|
|
300
|
||
|
|
],
|
||
|
|
"id": "e9b3fe87-c7c3-5eaf-897f-45406aefb704"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"name": "Checked?",
|
||
|
|
"type": "n8n-nodes-base.if",
|
||
|
|
"typeVersion": 2.2,
|
||
|
|
"parameters": {
|
||
|
|
"conditions": {
|
||
|
|
"options": {
|
||
|
|
"caseSensitive": true,
|
||
|
|
"leftValue": "",
|
||
|
|
"typeValidation": "loose",
|
||
|
|
"version": 2
|
||
|
|
},
|
||
|
|
"conditions": [
|
||
|
|
{
|
||
|
|
"id": "c1",
|
||
|
|
"leftValue": "={{ Array.isArray($json.rows) && $json.rows.length > 0 }}",
|
||
|
|
"rightValue": "",
|
||
|
|
"operator": {
|
||
|
|
"type": "boolean",
|
||
|
|
"operation": "true",
|
||
|
|
"singleValue": true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
],
|
||
|
|
"combinator": "and"
|
||
|
|
},
|
||
|
|
"options": {}
|
||
|
|
},
|
||
|
|
"position": [
|
||
|
|
440,
|
||
|
|
300
|
||
|
|
],
|
||
|
|
"id": "78c41fec-cc62-5ce7-9c47-ae10eedd7245"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"name": "Reject body",
|
||
|
|
"type": "n8n-nodes-base.respondToWebhook",
|
||
|
|
"typeVersion": 1.1,
|
||
|
|
"parameters": {
|
||
|
|
"respondWith": "json",
|
||
|
|
"responseBody": "={{ JSON.stringify({ error: $json.error ?? 'check failed' }) }}",
|
||
|
|
"options": {
|
||
|
|
"responseCode": 400
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"position": [
|
||
|
|
660,
|
||
|
|
760
|
||
|
|
],
|
||
|
|
"id": "57d70716-121e-589f-9617-31756fb52264"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"name": "Batch ok?",
|
||
|
|
"type": "n8n-nodes-base.if",
|
||
|
|
"typeVersion": 2.2,
|
||
|
|
"parameters": {
|
||
|
|
"conditions": {
|
||
|
|
"options": {
|
||
|
|
"caseSensitive": true,
|
||
|
|
"leftValue": "",
|
||
|
|
"typeValidation": "loose",
|
||
|
|
"version": 2
|
||
|
|
},
|
||
|
|
"conditions": [
|
||
|
|
{
|
||
|
|
"id": "c1",
|
||
|
|
"leftValue": "={{ $json.invalid / $json.total <= ($('Import webhook').first().json.body.max_invalid_ratio ?? 0.3) }}",
|
||
|
|
"rightValue": "",
|
||
|
|
"operator": {
|
||
|
|
"type": "boolean",
|
||
|
|
"operation": "true",
|
||
|
|
"singleValue": true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
],
|
||
|
|
"combinator": "and"
|
||
|
|
},
|
||
|
|
"options": {}
|
||
|
|
},
|
||
|
|
"position": [
|
||
|
|
660,
|
||
|
|
300
|
||
|
|
],
|
||
|
|
"id": "a60e6dbb-88a3-59b1-9a97-6efe355e18f1"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"name": "Reject batch",
|
||
|
|
"type": "n8n-nodes-base.respondToWebhook",
|
||
|
|
"typeVersion": 1.1,
|
||
|
|
"parameters": {
|
||
|
|
"respondWith": "json",
|
||
|
|
"responseBody": "={{ JSON.stringify({ error: 'batch rejected', batch: $('Run check').first().json.batch, invalid_ratio: Math.round($('Run check').first().json.invalid / $('Run check').first().json.total * 10000) / 10000, max_invalid_ratio: ($('Import webhook').first().json.body.max_invalid_ratio ?? 0.3), codes: $('Run check').first().json.codes }) }}",
|
||
|
|
"options": {
|
||
|
|
"responseCode": 422
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"position": [
|
||
|
|
880,
|
||
|
|
560
|
||
|
|
],
|
||
|
|
"id": "a0faba36-ffdc-5d7c-a3ad-27655254174b"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"name": "Split rows",
|
||
|
|
"type": "n8n-nodes-base.code",
|
||
|
|
"typeVersion": 2,
|
||
|
|
"parameters": {
|
||
|
|
"jsCode": "const c = $('Run check').first().json;\nconst items = $('Import webhook').first().json.body.items;\nreturn c.rows.map((r, i) => ({ json: { ...r, row: items[i], batch: c.batch } }));"
|
||
|
|
},
|
||
|
|
"position": [
|
||
|
|
880,
|
||
|
|
300
|
||
|
|
],
|
||
|
|
"id": "666c96f6-be31-54d9-a0dc-924fb089b786"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"name": "Decide",
|
||
|
|
"type": "n8n-nodes-base.code",
|
||
|
|
"typeVersion": 2,
|
||
|
|
"parameters": {
|
||
|
|
"jsCode": "return $input.all();"
|
||
|
|
},
|
||
|
|
"position": [
|
||
|
|
1100,
|
||
|
|
300
|
||
|
|
],
|
||
|
|
"id": "8e4f7788-d9d4-513c-8702-1a4d0218faa5"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"name": "Store row",
|
||
|
|
"type": "n8n-nodes-base.httpRequest",
|
||
|
|
"typeVersion": 4.2,
|
||
|
|
"parameters": {
|
||
|
|
"url": "={{ $json.ok ? 'http://data-api:8800/faq/add' : 'http://data-api:8800/quarantine' }}",
|
||
|
|
"options": {
|
||
|
|
"response": {
|
||
|
|
"response": {
|
||
|
|
"neverError": true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"method": "POST",
|
||
|
|
"sendBody": true,
|
||
|
|
"specifyBody": "json",
|
||
|
|
"jsonBody": "={{ JSON.stringify($json.ok ? $json.row : { items: [{ batch: $json.batch, row: $json.row, errors: $json.errors }] }) }}"
|
||
|
|
},
|
||
|
|
"position": [
|
||
|
|
1320,
|
||
|
|
300
|
||
|
|
],
|
||
|
|
"id": "e35c6cb5-7cc0-5d07-8d38-68d6f7a116d4"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"name": "Summarize",
|
||
|
|
"type": "n8n-nodes-base.code",
|
||
|
|
"typeVersion": 2,
|
||
|
|
"parameters": {
|
||
|
|
"jsCode": "const c = $('Run check').first().json;\nconst rows = $('Decide').all().map((i) => i.json);\nconst imported = rows.filter((r) => r.ok);\nconst quarantined = rows.filter((r) => !r.ok);\nconst codes = { ...c.codes };\nfor (const r of quarantined) for (const e of r.errors) if (e === 'llm_mismatch') codes[e] = (codes[e] ?? 0) + 1;\nreturn [{ json: { batch: c.batch, total: c.total, imported: imported.length, quarantined: quarantined.length, rejected: false,\n score: Math.round(imported.length / c.total * 10000) / 10000, max_invalid_ratio: ($('Import webhook').first().json.body.max_invalid_ratio ?? 0.3),\n codes, imported_ids: imported.map((r) => r.id), quarantined_ids: quarantined.map((r) => r.id) } }];"
|
||
|
|
},
|
||
|
|
"position": [
|
||
|
|
1540,
|
||
|
|
300
|
||
|
|
],
|
||
|
|
"id": "80a8e374-c3d2-5f31-bce1-160bd265176c"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"name": "Send result",
|
||
|
|
"type": "n8n-nodes-base.respondToWebhook",
|
||
|
|
"typeVersion": 1.1,
|
||
|
|
"parameters": {
|
||
|
|
"respondWith": "json",
|
||
|
|
"responseBody": "={{ $json }}",
|
||
|
|
"options": {}
|
||
|
|
},
|
||
|
|
"position": [
|
||
|
|
1760,
|
||
|
|
300
|
||
|
|
],
|
||
|
|
"id": "861cf41c-8519-549b-ba20-7cd0943caf23"
|
||
|
|
}
|
||
|
|
],
|
||
|
|
"connections": {
|
||
|
|
"Import webhook": {
|
||
|
|
"main": [
|
||
|
|
[
|
||
|
|
{
|
||
|
|
"node": "Run check",
|
||
|
|
"type": "main",
|
||
|
|
"index": 0
|
||
|
|
}
|
||
|
|
]
|
||
|
|
]
|
||
|
|
},
|
||
|
|
"Run check": {
|
||
|
|
"main": [
|
||
|
|
[
|
||
|
|
{
|
||
|
|
"node": "Checked?",
|
||
|
|
"type": "main",
|
||
|
|
"index": 0
|
||
|
|
}
|
||
|
|
]
|
||
|
|
]
|
||
|
|
},
|
||
|
|
"Checked?": {
|
||
|
|
"main": [
|
||
|
|
[
|
||
|
|
{
|
||
|
|
"node": "Batch ok?",
|
||
|
|
"type": "main",
|
||
|
|
"index": 0
|
||
|
|
}
|
||
|
|
],
|
||
|
|
[
|
||
|
|
{
|
||
|
|
"node": "Reject body",
|
||
|
|
"type": "main",
|
||
|
|
"index": 0
|
||
|
|
}
|
||
|
|
]
|
||
|
|
]
|
||
|
|
},
|
||
|
|
"Batch ok?": {
|
||
|
|
"main": [
|
||
|
|
[
|
||
|
|
{
|
||
|
|
"node": "Split rows",
|
||
|
|
"type": "main",
|
||
|
|
"index": 0
|
||
|
|
}
|
||
|
|
],
|
||
|
|
[
|
||
|
|
{
|
||
|
|
"node": "Reject batch",
|
||
|
|
"type": "main",
|
||
|
|
"index": 0
|
||
|
|
}
|
||
|
|
]
|
||
|
|
]
|
||
|
|
},
|
||
|
|
"Split rows": {
|
||
|
|
"main": [
|
||
|
|
[
|
||
|
|
{
|
||
|
|
"node": "Decide",
|
||
|
|
"type": "main",
|
||
|
|
"index": 0
|
||
|
|
}
|
||
|
|
]
|
||
|
|
]
|
||
|
|
},
|
||
|
|
"Decide": {
|
||
|
|
"main": [
|
||
|
|
[
|
||
|
|
{
|
||
|
|
"node": "Store row",
|
||
|
|
"type": "main",
|
||
|
|
"index": 0
|
||
|
|
}
|
||
|
|
]
|
||
|
|
]
|
||
|
|
},
|
||
|
|
"Store row": {
|
||
|
|
"main": [
|
||
|
|
[
|
||
|
|
{
|
||
|
|
"node": "Summarize",
|
||
|
|
"type": "main",
|
||
|
|
"index": 0
|
||
|
|
}
|
||
|
|
]
|
||
|
|
]
|
||
|
|
},
|
||
|
|
"Summarize": {
|
||
|
|
"main": [
|
||
|
|
[
|
||
|
|
{
|
||
|
|
"node": "Send result",
|
||
|
|
"type": "main",
|
||
|
|
"index": 0
|
||
|
|
}
|
||
|
|
]
|
||
|
|
]
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"settings": {
|
||
|
|
"executionOrder": "v1"
|
||
|
|
}
|
||
|
|
}
|