Files
truenas-stacks/n8n-workflows/05-paperless-to-rag-v1.0.json
2026-05-09 13:51:58 -05:00

357 lines
11 KiB
JSON

{
"updatedAt": "2026-05-07T00:48:49.355Z",
"createdAt": "2026-05-07T00:48:49.355Z",
"id": "4YKnRQ9rOiQCeYEU",
"name": "Paperless \u2192 RAG v1.0",
"description": null,
"active": true,
"isArchived": false,
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "paperless/rag-ingest",
"options": {}
},
"id": "a86d7025-bbf0-4c1b-a59c-ad254ddc913e",
"name": "Paperless RAG Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
0,
0
],
"webhookId": "f2eccecb-9935-425b-be6a-f57fe4473f34"
},
{
"parameters": {
"jsCode": "const data = $input.first().json;\nconst body = data.body || data;\n\nlet docId = body.document_id || body.id || body.doc_id || body.pk;\n\nif (!docId || typeof docId === 'string' && docId.includes('{')) {\n docId = null;\n}\n\nreturn [{ json: { docId } }];"
},
"id": "8f6af849-bdd9-466e-af81-84d057fd7ca1",
"name": "Extract Document ID",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
224,
0
]
},
{
"parameters": {
"url": "=https://paperless.paccoco.com/api/documents/{{ $json.docId ? $json.docId + '/' : '?ordering=-added&page_size=1' }}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Token 4fb34ba35b4ab76a0715e8c56faf00a31de4fb5d"
}
]
},
"options": {}
},
"id": "0b53d951-40cd-4ef0-ab81-3dea73f8b1d7",
"name": "Fetch Document",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
448,
0
]
},
{
"parameters": {
"jsCode": "const response = $input.first().json;\nconst doc = response.results ? response.results[0] : response;\n\nif (!doc || !doc.id) {\n throw new Error('No document found in response');\n}\n\nconst content = doc.content || '';\nconst title = doc.title || 'Untitled';\nconst correspondent = doc.correspondent_name || 'Unknown';\nconst created = doc.created || new Date().toISOString();\nconst docType = doc.document_type_name || 'unknown';\nconst tags = (doc.tags || []).join(', ');\n\n// Build rich text for RAG with metadata context\nconst ragText = `Document: ${title}\\nCorrespondent: ${correspondent}\\nType: ${docType}\\nTags: ${tags}\\nDate: ${created}\\n\\n${content}`;\n\nreturn [{\n json: {\n documentId: doc.id,\n title,\n ragText,\n source: `paperless-doc-${doc.id}`,\n metadata: {\n paperless_id: doc.id,\n title,\n correspondent,\n document_type: docType,\n created\n }\n }\n}];"
},
"id": "e3d506bc-1677-4825-b3d3-f6187156da22",
"name": "Prepare RAG Text",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
672,
0
]
},
{
"parameters": {
"jsCode": "// Split text into chunks for embedding\nconst input = $input.first().json;\nconst text = input.ragText || '';\nconst source = input.source;\nconst metadata = input.metadata;\n\nconst CHUNK_SIZE = 500;\nconst OVERLAP = 50;\n\nconst chunks = [];\nconst sentences = text.split(/(?<=[.!?])\\s+/);\nlet current = '';\n\nfor (const sentence of sentences) {\n if ((current + ' ' + sentence).length > CHUNK_SIZE && current.length > 0) {\n chunks.push(current.trim());\n const words = current.split(' ');\n current = words.slice(-OVERLAP).join(' ') + ' ' + sentence;\n } else {\n current = current ? current + ' ' + sentence : sentence;\n }\n}\nif (current.trim()) chunks.push(current.trim());\n\nreturn chunks.map((chunk, i) => ({\n json: {\n chunk,\n chunkIndex: i,\n totalChunks: chunks.length,\n source,\n metadata\n }\n}));"
},
"id": "9a523501-3adb-41a3-b963-b6bb5adb25fe",
"name": "Chunk Text",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
880,
0
]
},
{
"parameters": {
"method": "POST",
"url": "http://10.5.1.6:11434/v1/embeddings",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"model\": \"nomic-embed-text\",\n \"input\": \"{{ $json.chunk }}\"\n}",
"options": {
"batching": {
"batch": {
"batchSize": 5,
"batchInterval": 500
}
}
}
},
"id": "0b631ea4-b11f-4533-960f-f5161ac798f3",
"name": "Get Embedding",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1104,
0
]
},
{
"parameters": {
"jsCode": "const embeddingResponse = $input.first().json;\nconst chunkData = $('Chunk Text').item;\nconst embedding = embeddingResponse.data?.[0]?.embedding || [];\n\nconst pointId = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {\n const r = Math.random() * 16 | 0;\n return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);\n});\n\nreturn [{\n json: {\n id: pointId,\n vector: embedding,\n payload: {\n text: chunkData.json.chunk,\n source: chunkData.json.source,\n chunkIndex: chunkData.json.chunkIndex,\n totalChunks: chunkData.json.totalChunks,\n metadata: chunkData.json.metadata,\n ingested_at: new Date().toISOString()\n }\n }\n}];"
},
"id": "ad9dc677-e3a2-464e-a82e-2aa4d8b9b042",
"name": "Prepare Qdrant Point",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1328,
0
]
},
{
"parameters": {
"method": "PUT",
"url": "http://10.5.1.6:6333/collections/knowledge_base/points",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"points\": [\n {\n \"id\": \"{{ $json.id }}\",\n \"vector\": {{ JSON.stringify($json.vector) }},\n \"payload\": {{ JSON.stringify($json.payload) }}\n }\n ]\n}",
"options": {}
},
"id": "e977b536-d470-4da0-a970-794a858e8aa9",
"name": "Upsert to Qdrant",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1552,
0
]
},
{
"parameters": {
"jsCode": "const ragText = $('Prepare RAG Text').first().json;\nconst chunks = $('Chunk Text').first().json;\nreturn [{\n json: {\n title: '\ud83d\udcda Document Added to RAG',\n message: `${ragText.title} has been chunked and ingested into the knowledge base (${chunks.totalChunks || '?'} chunks)`,\n priority: 3\n }\n}];"
},
"id": "fmt05-0001-0000-0000-000000000005",
"name": "Format Gotify Message",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1520,
0
]
},
{
"parameters": {
"message": "={{ $json.message }}",
"additionalFields": {
"priority": "={{ $json.priority }}",
"title": "={{ $json.title }}"
},
"options": {
"contentType": "text/plain"
}
},
"id": "ccdee208-b8f8-4ad4-a20c-94c4735d2e3d",
"name": "Notify via Gotify",
"type": "n8n-nodes-base.gotify",
"typeVersion": 1,
"position": [
1760,
0
],
"credentials": {
"gotifyApi": {
"id": "SETUP_REQUIRED",
"name": "Paperless RAG"
}
}
}
],
"connections": {
"Paperless RAG Webhook": {
"main": [
[
{
"node": "Extract Document ID",
"type": "main",
"index": 0
}
]
]
},
"Extract Document ID": {
"main": [
[
{
"node": "Fetch Document",
"type": "main",
"index": 0
}
]
]
},
"Fetch Document": {
"main": [
[
{
"node": "Prepare RAG Text",
"type": "main",
"index": 0
}
]
]
},
"Prepare RAG Text": {
"main": [
[
{
"node": "Chunk Text",
"type": "main",
"index": 0
}
]
]
},
"Chunk Text": {
"main": [
[
{
"node": "Get Embedding",
"type": "main",
"index": 0
}
]
]
},
"Get Embedding": {
"main": [
[
{
"node": "Prepare Qdrant Point",
"type": "main",
"index": 0
}
]
]
},
"Prepare Qdrant Point": {
"main": [
[
{
"node": "Upsert to Qdrant",
"type": "main",
"index": 0
}
]
]
},
"Upsert to Qdrant": {
"main": [
[
{
"node": "Format Gotify Message",
"type": "main",
"index": 0
}
]
]
},
"Format Gotify Message": {
"main": [
[
{
"node": "Notify via Gotify",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1",
"binaryMode": "separate"
},
"staticData": null,
"meta": null,
"pinData": {},
"versionId": "3c20b423-8708-4540-8bf9-8db4880335a5",
"activeVersionId": "3c20b423-8708-4540-8bf9-8db4880335a5",
"versionCounter": 12,
"triggerCount": 1,
"tags": [
{
"updatedAt": "2026-05-06T22:39:46.476Z",
"createdAt": "2026-05-06T22:39:46.476Z",
"id": "NxHjuO4MMd5kdPR7",
"name": "paperless"
},
{
"updatedAt": "2026-05-06T22:39:33.284Z",
"createdAt": "2026-05-06T22:39:33.284Z",
"id": "7uuEyQrIlcuruZBk",
"name": "rag"
},
{
"updatedAt": "2026-05-06T22:38:51.678Z",
"createdAt": "2026-05-06T22:38:51.678Z",
"id": "S9FxzVfHLsHmyzyt",
"name": "ai"
}
],
"shared": [
{
"updatedAt": "2026-05-07T00:48:49.355Z",
"createdAt": "2026-05-07T00:48:49.355Z",
"role": "workflow:owner",
"workflowId": "4YKnRQ9rOiQCeYEU",
"projectId": "dxCRnBdX5uJizCGa",
"project": {
"updatedAt": "2026-05-06T01:10:37.484Z",
"createdAt": "2026-05-06T01:08:07.721Z",
"id": "dxCRnBdX5uJizCGa",
"name": "Wilfred Fizzlepoof <admin@paccoco.com>",
"type": "personal",
"icon": null,
"description": null,
"creatorId": "47b2227f-2fc2-4a08-bd35-ea157b92df0d"
}
}
],
"versionMetadata": {
"name": "Version 3c20b423",
"description": ""
}
}