Advanced RAG Chatbot (supports files and images)
Automated RAG pipeline that monitors Google Drive folders and processes PDFs into a queryable knowledge base with multimodal support (text + images).
Key Features:
- Multimodal OCR: Extracts and stores images with AI annotations using Mistral OCR
- Advanced Retrieval: Hybrid search (vector + keyword) with Cohere reranking
- Contextual Chunking: Each chunk gets situational context via GPT for better retrieval
- Smart Deduplication: Hash-based tracking prevents reprocessing unchanged files
- Stack: Supabase (vector store + image storage), OpenAI embeddings, conversational chat interface with memory
Shared 1/7/2026
9 views
Visual Workflow
JSON Code
{
"meta": {
"instanceId": "125637e355429ab06f8886794f7df9252a3e338f92a1957141a8989e48f2b612",
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "b6f5710d-73c7-4661-8868-1dac8e2ba8db",
"name": "Lookup Existing Record",
"type": "n8n-nodes-base.supabase",
"position": [
-2112,
1472
],
"parameters": {
"limit": 1,
"schema": "={{ $('Configure Settings').item.json.schema }}",
"filters": {
"conditions": [
{
"keyName": "file_id",
"keyValue": "={{ $('Configure Settings').item.json.file_id }}",
"condition": "eq"
}
]
},
"tableId": "record_manager_hybrid",
"operation": "getAll",
"useCustomSchema": true
},
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "9a84a054-252d-4f92-b4ec-23bf40e0030e",
"name": "Delete Record on File Update",
"type": "n8n-nodes-base.supabase",
"position": [
-1216,
2032
],
"parameters": {
"schema": "={{ $('Configure Settings').item.json.schema }}",
"filters": {
"conditions": [
{
"keyName": "file_id",
"keyValue": "={{ $('Batch Process Files').item.json.id }}",
"condition": "eq"
}
]
},
"tableId": "record_manager_hybrid",
"operation": "delete",
"useCustomSchema": true
},
"typeVersion": 1
},
{
"id": "6aace1bc-a139-42f1-baab-adff6d551d0a",
"name": "Set File ID from Drive",
"type": "n8n-nodes-base.set",
"position": [
-3696,
480
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "f4d00b47-6618-4f0b-baa3-80509c598f52",
"name": "file_id",
"type": "string",
"value": "={{ $json.id }}"
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "3aafd1ad-f794-44cf-90d4-bfaefd2c12d7",
"name": "Set File ID from Database",
"type": "n8n-nodes-base.set",
"position": [
-3696,
672
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "f4d00b47-6618-4f0b-baa3-80509c598f52",
"name": "file_id",
"type": "string",
"value": "={{ $json.file_id }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "2b1954c8-21f2-4912-b29c-a9faac4b4494",
"name": "Loop Over Deleted Files",
"type": "n8n-nodes-base.splitInBatches",
"position": [
-3472,
576
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "7005b90d-85e9-4e8d-b887-7da0a1cc0229",
"name": "Delete File Vectors from Documents",
"type": "n8n-nodes-base.supabase",
"position": [
-3248,
496
],
"parameters": {
"schema": "={{ $('Set Sync Config').item.json.schema }}",
"tableId": "documents_hybrid",
"operation": "delete",
"filterType": "string",
"filterString": "=metadata->>file_id=like.*{{ $json.file_id }}*",
"useCustomSchema": true
},
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "67edb6f3-6406-4f08-bb25-f5df7d54d95b",
"name": "Delete File From Record Manager",
"type": "n8n-nodes-base.supabase",
"position": [
-3024,
496
],
"parameters": {
"schema": "={{ $('Set Sync Config').item.json.schema }}",
"filters": {
"conditions": [
{
"keyName": "file_id",
"keyValue": "={{ $('Loop Over Deleted Files').item.json.file_id }}",
"condition": "eq"
}
]
},
"tableId": "record_manager_hybrid",
"operation": "delete",
"useCustomSchema": true
},
"executeOnce": false,
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "7551f096-a54c-43e3-9c94-d94349af0d42",
"name": "Delete Images from Storage (Deletion)",
"type": "n8n-nodes-base.postgres",
"position": [
-2800,
576
],
"parameters": {
"query": "DELETE FROM storage.objects\n WHERE bucket_id = '{{ $('Set Sync Config').item.json.image_bucket_name }}'\n AND name LIKE '{{ $('Loop Over Deleted Files').item.json.file_id }}/%';",
"options": {},
"operation": "executeQuery"
},
"typeVersion": 2.6
},
{
"id": "d0d9b2e0-4ad1-40d9-a992-802071d8235d",
"name": "Filter Non-Trashed Files",
"type": "n8n-nodes-base.filter",
"position": [
-3920,
480
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "98f8e6e3-6f28-423c-b33b-7d19cd4c386b",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $json.trashed }}",
"rightValue": false
}
]
}
},
"typeVersion": 2.2
},
{
"id": "6879fda1-5d3d-468d-84be-72d320c4637f",
"name": "Filter Trashed Files",
"type": "n8n-nodes-base.filter",
"position": [
-3920,
880
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "98f8e6e3-6f28-423c-b33b-7d19cd4c386b",
"operator": {
"type": "boolean",
"operation": "false",
"singleValue": true
},
"leftValue": "={{ $json.trashed }}",
"rightValue": false
}
]
}
},
"typeVersion": 2.2
},
{
"id": "b310c03d-d9f0-453c-82cf-221ab8942a60",
"name": "Set Sync Config",
"type": "n8n-nodes-base.set",
"position": [
-4816,
768
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "d1600621-59b2-4d69-b877-89285490a3b5",
"name": "folder_id",
"type": "string",
"value": "1kivpdS6ZFCJII6K6s8B0cjLJIUaqiYQv"
},
{
"id": "dd5117f1-5649-4aa5-8097-be41e45b23d4",
"name": "supabase_url",
"type": "string",
"value": "https://hpschyruavrtmhgbwcur.supabase.co"
},
{
"id": "402842bc-814f-46c2-ad2d-7c08ed3cda8c",
"name": "image_bucket_name",
"type": "string",
"value": "leo_rag_pdf_images"
},
{
"id": "6222704b-408b-46a0-a72d-141a346880f2",
"name": "schema",
"type": "string",
"value": "ht_rag_chatbot"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "2aadb3b3-7fdd-4d36-bc41-cc2d9b2cd6bc",
"name": "Split Drive Files",
"type": "n8n-nodes-base.splitOut",
"position": [
-4368,
864
],
"parameters": {
"options": {},
"fieldToSplitOut": "files"
},
"typeVersion": 1
},
{
"id": "6c7f8576-5901-4d60-99e5-a35bf9a9828b",
"name": "Compare Drive vs Database",
"type": "n8n-nodes-base.compareDatasets",
"position": [
-4144,
736
],
"parameters": {
"options": {},
"resolve": "preferInput2",
"mergeByFields": {
"values": [
{
"field1": "file_id",
"field2": "id"
}
]
}
},
"typeVersion": 2.3
},
{
"id": "915fe8e3-d074-4ea7-97a3-2880138caaf4",
"name": "Get All Record Manager Rows",
"type": "n8n-nodes-base.supabase",
"position": [
-4368,
672
],
"parameters": {
"schema": "={{ $('Set Sync Config').item.json.schema }}",
"tableId": "record_manager_hybrid",
"operation": "getAll",
"returnAll": true,
"filterType": "none",
"useCustomSchema": true
},
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "f5bc9517-838c-42cc-85ac-577e34d00ae1",
"name": "List Files in Google Drive",
"type": "n8n-nodes-base.httpRequest",
"position": [
-4592,
864
],
"parameters": {
"url": "https://www.googleapis.com/drive/v3/files",
"options": {},
"sendQuery": true,
"authentication": "predefinedCredentialType",
"queryParameters": {
"parameters": [
{
"name": "q",
"value": "='{{ $json.folder_id }}' in parents"
},
{
"name": "fields",
"value": "files(id,name,trashed,mimeType)"
}
]
},
"nodeCredentialType": "googleDriveOAuth2Api"
},
"retryOnFail": true,
"typeVersion": 4.3
},
{
"id": "a3abea34-b533-4345-9f6a-44709467a535",
"name": "Delete Images from Storage (Update)",
"type": "n8n-nodes-base.postgres",
"position": [
-1440,
2032
],
"parameters": {
"query": "DELETE FROM storage.objects\n WHERE bucket_id = '{{ $('Configure Settings').item.json.images_bucket_name }}'\n AND name LIKE '{{ $('Batch Process Files').item.json.id }}/%';",
"options": {},
"operation": "executeQuery"
},
"typeVersion": 2.6
},
{
"id": "6405fbfb-5dd4-4dc4-94e9-6b4078c7cee2",
"name": "Upload Image to Storage",
"type": "n8n-nodes-base.httpRequest",
"position": [
2368,
224
],
"parameters": {
"url": "={{ $('Configure Settings').item.json.supabase_url }}/storage/v1/object/{{ $('Configure Settings').item.json.images_bucket_name }}/{{ $('Batch Process Files').item.json.id }}/{{ $binary.data.fileName.replace(/[^a-zA-Z0-9._-]/g, '_').replace(/(\\.[^.]+)$/, '_' + Date.now() + '$1') }}",
"method": "POST",
"options": {},
"sendBody": true,
"contentType": "binaryData",
"sendHeaders": true,
"authentication": "predefinedCredentialType",
"headerParameters": {
"parameters": [
{
"name": "x-upsert",
"value": "true"
}
]
},
"inputDataFieldName": "data",
"nodeCredentialType": "supabaseApi"
},
"typeVersion": 4.3
},
{
"id": "b7f0c37f-d95a-43df-955f-466bffe86ff4",
"name": "On File Updated",
"type": "n8n-nodes-base.googleDriveTrigger",
"position": [
-4032,
2064
],
"parameters": {
"event": "fileUpdated",
"options": {},
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
},
"triggerOn": "specificFolder",
"folderToWatch": {
"__rl": true,
"mode": "id",
"value": "1kivpdS6ZFCJII6K6s8B0cjLJIUaqiYQv"
}
},
"typeVersion": 1
},
{
"id": "a7fdac90-32ec-4438-bc4f-de518cb41de8",
"name": "Processing Complete",
"type": "n8n-nodes-base.noOp",
"position": [
4928,
736
],
"parameters": {},
"typeVersion": 1
},
{
"id": "aac0193a-d569-4a80-b4f3-df7b7db6f51a",
"name": "Set Hash Record Id",
"type": "n8n-nodes-base.set",
"position": [
-320,
1472
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "ee2312c9-bd26-4ad2-92a2-b0bcd6d980a2",
"name": "hash_record_id",
"type": "number",
"value": "={{ $json.id }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "6e29bd16-bcad-4ad6-adf4-fe1e6ac1ef45",
"name": "Set Data Type Tabular",
"type": "n8n-nodes-base.set",
"position": [
-768,
2032
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "69af840b-111b-40f9-afc2-114e11726465",
"name": "data_type",
"type": "string",
"value": "tabular"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "b96352b3-f4ea-4724-9675-df2e7fc0ad1a",
"name": "Set Data Type Unstructured",
"type": "n8n-nodes-base.set",
"position": [
-768,
1376
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "69af840b-111b-40f9-afc2-114e11726465",
"name": "data_type",
"type": "string",
"value": "unstructured"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "7c8ae559-c8a9-4875-8a26-2105061cb172",
"name": "Set Combined Text",
"type": "n8n-nodes-base.set",
"position": [
4192,
736
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "7d83717d-3669-4250-88e9-c68a1c32478f",
"name": "text",
"type": "string",
"value": "={{ $json.text }}"
},
{
"id": "98d90eec-3928-46df-85cf-47eb02d90252",
"name": "file_id",
"type": "string",
"value": "={{ $('Configure Settings').first().json.file_id }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "60d2e3d1-a695-473e-8c36-82e0762cc1fe",
"name": "Handle OCR Failure",
"type": "n8n-nodes-base.noOp",
"position": [
1248,
848
],
"parameters": {},
"typeVersion": 1
},
{
"id": "edf278a6-7f37-468e-b161-ba2056d22e1f",
"name": "Extract Text from Plain Files",
"type": "n8n-nodes-base.extractFromFile",
"position": [
608,
1056
],
"parameters": {
"options": {},
"operation": "text",
"destinationKey": "text"
},
"typeVersion": 1.1
},
{
"id": "d18fba34-eccf-4946-912d-38ebb4fe4a7a",
"name": "Combine Markdown Pages",
"type": "n8n-nodes-base.code",
"position": [
3904,
448
],
"parameters": {
"jsCode": "// Get all input items\nconst items = $input.all();\n\n// Get Supabase configuration\nconst supabaseUrl = $('Configure Settings').first().json.supabase_url;\nconst bucketName = $('Configure Settings').first().json.images_bucket_name;\nconst fileId = $('Batch Process Files').first().json.id;\nconst fullBaseUrl = `${supabaseUrl}/storage/v1/object/public/${bucketName}/${fileId}/`;\n\n// Get uploaded images\nconst mergeItem = $('Merge OCR with Uploads').first().json;\nconst uploadedImages = mergeItem?.uploaded_images || [];\n\n// Process each item and collect markdown\nconst processedMarkdowns = items.map(item => {\n let markdown = item.json.markdown;\n \n if (Array.isArray(uploadedImages) && uploadedImages.length > 0) {\n for (const image of uploadedImages) {\n const originalId = image.original_id;\n const fileName = image.file_name;\n const annotation = image.annotation || '';\n \n const localPattern = ``;\n const hostedReplacement = `\\n\\n${annotation}`;\n \n if (markdown.includes(localPattern)) {\n markdown = markdown.replaceAll(localPattern, hostedReplacement);\n }\n }\n }\n \n return markdown;\n});\n\n// Combine all markdown\nconst combinedMarkdown = processedMarkdowns.join('\\n\\n');\n\n\nconst docId = $('Configure Settings').first().json.file_id\n\n// Return single item\nreturn {\n json: {\n text: combinedMarkdown,\n file_id: docId\n }\n};"
},
"typeVersion": 2
},
{
"id": "8bf19a85-85e3-4353-8845-7a1e50b6b221",
"name": "Route by File Type",
"type": "n8n-nodes-base.switch",
"position": [
352,
1072
],
"parameters": {
"rules": {
"values": [
{
"outputKey": "PDF",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "fdd3d7f5-c54b-41be-8c51-b2e2e9608e82",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "=application/pdf"
}
]
},
"renameOutput": true
},
{
"outputKey": "Google Doc",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "4fcff5dd-c89b-45ef-bf5d-be040e9ddc8f",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "application/vnd.google-apps.document"
}
]
},
"renameOutput": true
},
{
"outputKey": "DOCX",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "98339dcd-3d32-4301-89e8-a8253b2ee5e6",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
}
]
},
"renameOutput": true
},
{
"outputKey": "DOC",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "1eb632fb-11cf-4030-b852-7949411760b3",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "application/msword"
}
]
},
"renameOutput": true
},
{
"outputKey": "RTF",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "a9d8a4c3-621d-4793-971f-c7d4195bacb6",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "text/rtf"
}
]
},
"renameOutput": true
},
{
"outputKey": "ODT",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "62d9a39d-1a0a-4308-88e2-5037896e3322",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "application/vnd.oasis.opendocument.text"
}
]
},
"renameOutput": true
},
{
"outputKey": "PPTX",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "c37ff00f-1777-403b-808a-aa7224c7e92a",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "application/vnd.openxmlformats-officedocument.presentationml.presentation"
}
]
},
"renameOutput": true
},
{
"outputKey": "PPT",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "39254a94-bfd6-4d89-ae1e-5ffa6f88a313",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "application/vnd.ms-powerpoint"
}
]
},
"renameOutput": true
},
{
"outputKey": "TXT",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "10171128-3096-4715-b4af-65ba8e3e9622",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "text/plain"
}
]
},
"renameOutput": true
},
{
"outputKey": "MD",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "4072555c-a5c8-42db-866f-627832cfb96f",
"operator": {
"type": "string",
"operation": "contains"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "markdown"
}
]
},
"renameOutput": true
},
{
"outputKey": "CSV",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "84139a61-d41f-401a-b622-63dc2eede11d",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "text/csv"
}
]
},
"renameOutput": true
},
{
"outputKey": "XLSX",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "2b85801c-9412-4e0f-b3e1-10a64cb93b20",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
}
]
},
"renameOutput": true
},
{
"outputKey": "XLS",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "042b4f32-1d14-4aa7-b944-0b6a33a7f2a3",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "application/vnd.ms-excel"
}
]
},
"renameOutput": true
},
{
"outputKey": "Google Sheets",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "0fde8f16-1a0b-410b-8217-663581a5b29a",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "application/vnd.google-apps.spreadsheet"
}
]
},
"renameOutput": true
}
]
},
"options": {}
},
"typeVersion": 3.3
},
{
"id": "fe696b63-d2b2-4cc5-85a6-a633f8aec615",
"name": "Generate Embedding",
"type": "n8n-nodes-base.httpRequest",
"position": [
5440,
544
],
"parameters": {
"url": "https://api.openai.com/v1/embeddings",
"method": "POST",
"options": {},
"jsonBody": "={\n \"input\": {{ JSON.stringify($json.content) }},\n \"model\": \"text-embedding-3-small\"\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "openAiApi"
},
"typeVersion": 4.2
},
{
"id": "7172d202-75f2-453f-b82c-2f6947e3b4e6",
"name": "Images Exist?",
"type": "n8n-nodes-base.if",
"position": [
1472,
368
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "ef92ce6d-d5e6-4059-8a7d-d5b31ad82c2c",
"operator": {
"type": "array",
"operation": "lengthGt",
"rightType": "number"
},
"leftValue": "={{ $json.images }}",
"rightValue": 0
}
]
}
},
"typeVersion": 2.2
},
{
"id": "b9f8f5c7-e5c3-479f-84d3-c2290aec553d",
"name": "Extract Search Results",
"type": "n8n-nodes-base.splitOut",
"position": [
-3904,
3936
],
"parameters": {
"options": {},
"fieldToSplitOut": "results"
},
"typeVersion": 1
},
{
"id": "6df21cdb-fcf4-4b55-91ee-5276e2f807dc",
"name": "Return Error Message",
"type": "n8n-nodes-base.set",
"position": [
-3232,
4272
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "7f7c1fed-16ff-42ec-9d73-1df3e8c6055c",
"name": "response",
"type": "string",
"value": "Error retrieving information from knowledgebase"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "1f2c3914-a215-4ee2-ab1a-1ab7ac56bf15",
"name": "Split Pages for Processing",
"type": "n8n-nodes-base.splitOut",
"position": [
3616,
448
],
"parameters": {
"options": {},
"fieldToSplitOut": "pages"
},
"typeVersion": 1
},
{
"id": "03632dfa-4207-4c15-b8ae-ae6cc6a670e2",
"name": "Merge OCR with Uploads",
"type": "n8n-nodes-base.merge",
"position": [
3392,
448
],
"parameters": {
"mode": "combine",
"options": {},
"combineBy": "combineByPosition"
},
"typeVersion": 3.2
},
{
"id": "27c9fa8c-8482-4f8a-ae6c-5fd5f352e362",
"name": "Collect Uploaded Images",
"type": "n8n-nodes-base.aggregate",
"position": [
3168,
304
],
"parameters": {
"options": {},
"aggregate": "aggregateAllItemData",
"destinationFieldName": "uploaded_images"
},
"typeVersion": 1
},
{
"id": "ec0e3c16-4976-4eb6-b9ec-17434eaa94f0",
"name": "Merge Upload Response",
"type": "n8n-nodes-base.merge",
"position": [
2944,
304
],
"parameters": {
"mode": "combine",
"options": {},
"fieldsToMatchString": "file_name"
},
"typeVersion": 3.2
},
{
"id": "535edb16-fe5a-4e6c-951a-8c661567512e",
"name": "Extract Uploaded Filename",
"type": "n8n-nodes-base.set",
"position": [
2656,
224
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "8eef3a50-de55-414e-b0b6-f8779eddf55d",
"name": "file_name",
"type": "string",
"value": "={{ $json.Key.split('/')[2] }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "ae3ca472-90fb-4045-b1a9-1c490e7e9f80",
"name": "Convert Base64 to Binary",
"type": "n8n-nodes-base.convertToFile",
"position": [
2144,
224
],
"parameters": {
"options": {
"fileName": "={{ $json.file_name }}"
},
"operation": "toBinary",
"sourceProperty": "image_base64"
},
"typeVersion": 1.1
},
{
"id": "f272cb81-e450-4350-ada6-fc42b535a337",
"name": "Prepare Image Metadata",
"type": "n8n-nodes-base.set",
"position": [
1920,
304
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "de9477d9-79df-467f-a4e2-d9eaf8955228",
"name": "file_name",
"type": "string",
"value": "={{ Array.from({length: 32}, () => 'abcdefghijklmnopqrstuvwxyz0123456789'[Math.floor(Math.random() * 36)]).join('') }}"
},
{
"id": "1beb4dbb-b25b-44c4-bb01-33c43747f37a",
"name": "original_id",
"type": "string",
"value": "={{ $json.id }}"
},
{
"id": "c5a0631f-0acb-4566-9866-c6a2f2f3d731",
"name": "annotation",
"type": "string",
"value": "={{ JSON.parse($json.image_annotation).summary }}\n"
},
{
"id": "1e1d7a52-c5b1-4c6e-bd50-422cf03be7fb",
"name": "image_base64",
"type": "string",
"value": "={{ $json.image_base64.split(',')[1] }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "590350a4-4083-4134-82fb-66d55b957291",
"name": "Extract Images from Pages",
"type": "n8n-nodes-base.splitOut",
"position": [
1696,
304
],
"parameters": {
"options": {},
"fieldToSplitOut": "images"
},
"typeVersion": 1
},
{
"id": "c7e1c9d7-9a87-4914-841f-4963de7c067d",
"name": "Extract Pages",
"type": "n8n-nodes-base.splitOut",
"position": [
1248,
368
],
"parameters": {
"options": {},
"fieldToSplitOut": "pages"
},
"typeVersion": 1
},
{
"id": "f1c4cb20-6836-455b-8cb4-d06f59a186db",
"name": "Process with Mistral OCR",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueErrorOutput",
"position": [
1024,
608
],
"parameters": {
"url": "https://api.mistral.ai/v1/ocr",
"method": "POST",
"options": {
"redirect": {
"redirect": {}
},
"response": {
"response": {
"responseFormat": "json"
}
}
},
"jsonBody": "={\n \"model\": \"mistral-ocr-latest\",\n \"document\": {\n \"document_url\": \"{{ $json.url }}\"\n },\n \"bbox_annotation_format\": {\n \"type\": \"json_schema\",\n \"json_schema\": {\n \"schema\": {\n \"properties\": {\n \"document_type\": {\n \"title\": \"Document_Type\",\n \"description\": \"The type of the image.\",\n \"type\": \"string\"\n },\n \"short_description\": {\n \"title\": \"Short_Description\",\n \"description\": \"A description in English describing the image.\",\n \"type\": \"string\"\n },\n \"summary\": {\n \"title\": \"Summary\",\n \"description\": \"Summarize the image.\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"document_type\",\n \"short_description\",\n \"summary\"\n ],\n \"title\": \"BBOXAnnotation\",\n \"type\": \"object\",\n \"additionalProperties\": false\n },\n \"name\": \"document_annotation\",\n \"strict\": true\n }\n },\n \"include_image_base64\": true\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "mistralCloudApi"
},
"retryOnFail": true,
"typeVersion": 4.3,
"waitBetweenTries": 5000
},
{
"id": "7333f860-1163-447d-9bcd-cbc8af19fcde",
"name": "Get Mistral File URL",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueErrorOutput",
"position": [
800,
688
],
"parameters": {
"url": "=https://api.mistral.ai/v1/files/{{ $json.id }}/url",
"options": {},
"sendQuery": true,
"sendHeaders": true,
"authentication": "predefinedCredentialType",
"queryParameters": {
"parameters": [
{
"name": "expiry",
"value": "24"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "Accept",
"value": "application/json"
}
]
},
"nodeCredentialType": "mistralCloudApi"
},
"retryOnFail": true,
"typeVersion": 4.3,
"waitBetweenTries": 5000
},
{
"id": "a39ab44f-80a9-415b-aef9-896bfca72d73",
"name": "Upload File to Mistral",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueErrorOutput",
"position": [
576,
688
],
"parameters": {
"url": "=https://api.mistral.ai/v1/files",
"method": "POST",
"options": {},
"sendBody": true,
"contentType": "multipart-form-data",
"authentication": "predefinedCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "purpose",
"value": "ocr"
},
{
"name": "file",
"parameterType": "formBinaryData",
"inputDataFieldName": "data"
}
]
},
"nodeCredentialType": "mistralCloudApi"
},
"retryOnFail": true,
"typeVersion": 4.3,
"waitBetweenTries": 5000
},
{
"id": "b575fed9-f059-44d8-86de-85c39c9439cb",
"name": "Rate Limit Delay",
"type": "n8n-nodes-base.wait",
"position": [
5888,
736
],
"webhookId": "e3664bfb-f033-46dc-a5a0-391710751b2a",
"parameters": {
"amount": 15
},
"typeVersion": 1.1
},
{
"id": "7930f4f8-52ed-4aa9-94fa-b61e9a5ab54f",
"name": "Merge Context with Chunk",
"type": "n8n-nodes-base.set",
"position": [
5216,
544
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "02c135df-ab85-4e76-affb-22ed7ecfd061",
"name": "content",
"type": "string",
"value": "={{ $json.message.content }} - {{ $('Batch Process Chunks').item.json.chunk }}"
},
{
"id": "88f3fce4-4be5-47fa-930b-42078a6a1458",
"name": "metadata",
"type": "object",
"value": "={{ { loc: { lines: { from: 1, to: 1 } }, source: \"blob\", blobType: \"application/json\", file_id: $('Set Combined Text').item.json.file_id } }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "3bd0597d-fbb2-453e-ab59-562e36122ae9",
"name": "Generate Chunk Context",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
4864,
544
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-5-nano-2025-08-07",
"cachedResultName": "GPT-5-NANO-2025-08-07"
},
"options": {},
"messages": {
"values": [
{
"content": "=<document> \n{{ $('Set Combined Text').item.json.text }}\n</document> \nHere is the chunk we want to situate within the whole document \n<chunk> \n{{ $('Batch Process Chunks').item.json.chunk }}\n</chunk> \nPlease give a short succinct context to situate this chunk within the overall document for the purposes of improving search retrieval of the chunk. Answer only with the succinct context and nothing else. Start with: \"This chunk contains...\""
}
]
}
},
"retryOnFail": true,
"typeVersion": 1.8,
"waitBetweenTries": 5000
},
{
"id": "c2972ec8-4e66-4ff5-90a3-da73cc028032",
"name": "Batch Process Chunks",
"type": "n8n-nodes-base.splitInBatches",
"position": [
4640,
736
],
"parameters": {
"options": {
"reset": "={{ $prevNode.name === 'Split Document into Chunks' }}"
},
"batchSize": 10
},
"typeVersion": 3
},
{
"id": "42770aa2-365d-45a7-ab79-dd5f996a24ae",
"name": "Split Document into Chunks",
"type": "n8n-nodes-base.code",
"position": [
4416,
736
],
"parameters": {
"jsCode": "// Define chunk size and overlap\nconst chunkSize = 2000;\nconst chunkOverlap = 200;\n\n// Function to split text into overlapping chunks\nfunction createChunks(text) {\n\tconst chunks = [];\n\tlet remainingText = text;\n\n\twhile (remainingText.length > 0) {\n\t\tlet splitPoint;\n\n\t\t// Try paragraph split first\n\t\tsplitPoint = remainingText.lastIndexOf(\"\\n\\n\", chunkSize);\n\n\t\t// If no paragraph split, try sentence split\n\t\tif (splitPoint === -1) {\n\t\t\tsplitPoint = remainingText.lastIndexOf(\". \", chunkSize);\n\t\t}\n\n\t\t// If no sentence split, try word split\n\t\tif (splitPoint === -1) {\n\t\t\tsplitPoint = remainingText.lastIndexOf(\" \", chunkSize);\n\t\t}\n\n\t\t// If still no split point, hard cut at chunkSize\n\t\tif (splitPoint === -1 || splitPoint < chunkSize * 0.5) {\n\t\t\tsplitPoint = chunkSize;\n\t\t}\n\n\t\t// Extract chunk\n\t\tconst chunk = remainingText.substring(0, splitPoint).trim();\n\t\tchunks.push(chunk);\n\n\t\t// Move pointer forward with overlap\n\t\tremainingText = remainingText.substring(Math.max(0, splitPoint - chunkOverlap)).trim();\n\n\t\t// Stop if remaining text too small\n\t\tif (remainingText.length < chunkSize * 0.2) {\n\t\t\tif (remainingText.length > 0) {\n\t\t\t\tchunks.push(remainingText);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn chunks;\n}\n\n// Take first incoming item's document and create chunks\nconst text = $input.first().json.text || '';\nconst chunks = createChunks(text);\n\n// Return one item per chunk\nreturn chunks.map(chunk => ({ json: { chunk } }));"
},
"typeVersion": 2
},
{
"id": "c8d545f4-7807-46d8-9196-d66c9f47c7da",
"name": "Format Reranked Output",
"type": "n8n-nodes-base.code",
"position": [
-3232,
3888
],
"parameters": {
"jsCode": " // Get the reranking results from the previous HTTP Request2 node\n const rerankResults = $input.all()[0].json;\n\n // Get the original aggregated content from the Aggregate node\n const originalContent = $('Collect Search Results').first().json.content;\n const originalIds = $('Collect Search Results').first().json.ids;\n const metadata = $('Collect Search Results').first().json.metadata;\n\n // Extract the reordered results from Cohere's response\n const reorderedResults = rerankResults.results;\n\n // Create the reordered chunks array\n const reorderedChunks = reorderedResults.map((result) => {\n return {\n id: originalIds[result.index],\n content: originalContent[result.index],\n type: metadata[result.index],\n relevance_score: result.relevance_score\n };\n });\n\n return [\n {\n json: {\n reordered_chunks: reorderedChunks,\n }\n }\n ];"
},
"typeVersion": 2
},
{
"id": "3c213fcd-661f-4e0c-8a88-ecab9d8f52e7",
"name": "Collect Search Results",
"type": "n8n-nodes-base.aggregate",
"position": [
-3680,
3936
],
"parameters": {
"options": {},
"fieldsToAggregate": {
"fieldToAggregate": [
{
"fieldToAggregate": "content"
},
{
"renameField": true,
"outputFieldName": "ids",
"fieldToAggregate": "id"
},
{
"fieldToAggregate": "metadata"
}
]
}
},
"typeVersion": 1
},
{
"id": "e20a5b0f-e134-436b-ba4c-da6c6d80e59c",
"name": "Rerank Results with Cohere",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueErrorOutput",
"position": [
-3456,
3936
],
"parameters": {
"url": "https://api.cohere.com/v2/rerank",
"method": "POST",
"options": {},
"jsonBody": "={\n \"model\": \"rerank-v3.5\",\n \"query\": \"{{ $('Execute Workflow Trigger').item.json.query }}\",\n \"top_n\": 5,\n \"documents\": {{ JSON.stringify($json.content) }}\n \n} ",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"headerParameters": {
"parameters": [
{
"name": "accept",
"value": "application/json"
}
]
},
"nodeCredentialType": "cohereApi"
},
"retryOnFail": true,
"typeVersion": 4.2
},
{
"id": "5788cdf8-b9d9-4e3e-81fd-2fafd54221f7",
"name": "Execute Hybrid Search",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueErrorOutput",
"position": [
-4352,
4112
],
"parameters": {
"url": "={{ $('Set Supabase Settings').item.json.supabase_url }}/functions/v1/hybrid_search",
"method": "POST",
"options": {
"response": {
"response": {
"responseFormat": "json"
}
}
},
"jsonBody": "={\n \"query_text\": {{ JSON.stringify($('Execute Workflow Trigger').item.json.query) }},\n \"query_embedding\": {{ JSON.stringify($json.data[0].embedding) }},\n \"debug\": true\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpBearerAuth"
},
"typeVersion": 4.2,
"alwaysOutputData": false
},
{
"id": "d90c6c1f-b205-4f89-89c4-bb351f8b8822",
"name": "Generate Query Embedding",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueErrorOutput",
"position": [
-4576,
4176
],
"parameters": {
"url": "https://api.openai.com/v1/embeddings",
"method": "POST",
"options": {},
"sendBody": true,
"authentication": "predefinedCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "input",
"value": "={{ $json.query }}"
},
{
"name": "model",
"value": "text-embedding-3-small"
}
]
},
"nodeCredentialType": "openAiApi"
},
"retryOnFail": true,
"typeVersion": 4.2
},
{
"id": "5d4ed4e0-f417-475a-87a8-46e0ea61c7a8",
"name": "Execute Workflow Trigger",
"type": "n8n-nodes-base.executeWorkflowTrigger",
"position": [
-5024,
4176
],
"parameters": {
"workflowInputs": {
"values": [
{
"name": "query"
}
]
}
},
"typeVersion": 1.1
},
{
"id": "877fbcb0-4099-4992-b530-5f1ca31accf6",
"name": "Download File for Processing",
"type": "n8n-nodes-base.googleDrive",
"position": [
144,
1264
],
"parameters": {
"fileId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Download File for Hash').item.json.id }}"
},
"options": {},
"operation": "download"
},
"typeVersion": 3
},
{
"id": "f0113cb8-27c2-43ac-84ea-a40d03ada53d",
"name": "Delete Existing Vectors",
"type": "n8n-nodes-base.supabase",
"position": [
-1664,
2032
],
"parameters": {
"schema": "={{ $('Configure Settings').item.json.schema }}",
"tableId": "documents_hybrid",
"operation": "delete",
"filterType": "string",
"filterString": "=metadata->>google_drive_file_id=like.*{{ $('Batch Process Files').item.json.id }}*",
"useCustomSchema": true
},
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "4b9a0d3c-b03c-4aff-a83b-54940a2fa815",
"name": "Route by Hash Status",
"type": "n8n-nodes-base.switch",
"position": [
-1888,
1472
],
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "546738cb-1f11-44bf-a5e7-f9526a378a67",
"operator": {
"type": "object",
"operation": "empty",
"singleValue": true
},
"leftValue": "={{ $json }}",
"rightValue": ""
}
]
}
},
{
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "015a91c1-8f02-4c05-945b-0b009034d418",
"operator": {
"type": "string",
"operation": "notEquals"
},
"leftValue": "={{ $json.hash }}",
"rightValue": "={{ $('Generate SHA256 Hash').item.json.hash }}"
}
]
}
}
]
},
"options": {}
},
"typeVersion": 3.2
},
{
"id": "55f19398-3848-4571-b34f-6d0a7dd853f4",
"name": "Insert Hash Record",
"type": "n8n-nodes-base.supabase",
"position": [
-544,
1472
],
"parameters": {
"schema": "={{ $('Configure Settings').item.json.schema }}",
"tableId": "record_manager_hybrid",
"fieldsUi": {
"fieldValues": [
{
"fieldId": "file_id",
"fieldValue": "={{ $('Configure Settings').item.json.file_id }}"
},
{
"fieldId": "hash",
"fieldValue": "={{ $('Generate SHA256 Hash').item.json.hash }}"
},
{
"fieldId": "data_type",
"fieldValue": "={{ $json.data_type }}"
},
{
"fieldId": "document_title",
"fieldValue": "={{ $('Configure Settings').item.json.title }}"
},
{
"fieldId": "record_type",
"fieldValue": "={{ $('Receive Firecrawl Events').isExecuted ? \"webpage\" : \"google_drive_file\" }}"
}
]
},
"useCustomSchema": true
},
"typeVersion": 1
},
{
"id": "eabbdb6b-d8b4-4c6b-a233-4540c3b031a9",
"name": "Generate SHA256 Hash",
"type": "n8n-nodes-base.crypto",
"position": [
-2336,
1472
],
"parameters": {
"type": "SHA256",
"binaryData": true,
"dataPropertyName": "hash"
},
"typeVersion": 1
},
{
"id": "e927c16f-6bd0-4614-adac-107cb4340e98",
"name": "Download File for Hash",
"type": "n8n-nodes-base.googleDrive",
"position": [
-2560,
2032
],
"parameters": {
"fileId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Batch Process Files').item.json.id }}"
},
"options": {},
"operation": "download"
},
"typeVersion": 3
},
{
"id": "748977fa-583b-46db-9ac3-b261ca387124",
"name": "Batch Process Files",
"type": "n8n-nodes-base.splitInBatches",
"position": [
-3808,
1888
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "86c08984-a291-4393-88e9-7bb4500135b6",
"name": "Set Supabase Settings",
"type": "n8n-nodes-base.set",
"position": [
-4800,
4176
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "7982c2ee-a7e4-4939-b84a-c810f5e50630",
"name": "supabase_url",
"type": "string",
"value": "https://hpschyruavrtmhgbwcur.supabase.co"
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "08849f86-8047-4327-9f3f-bedf570a7f02",
"name": "Insert into Supabase",
"type": "n8n-nodes-base.supabase",
"position": [
5664,
544
],
"parameters": {
"schema": "={{ $('Configure Settings').first().json.schema }}",
"tableId": "documents_hybrid",
"fieldsUi": {
"fieldValues": [
{
"fieldId": "content",
"fieldValue": "={{ JSON.stringify($('Merge Context with Chunk').item.json.content) }}"
},
{
"fieldId": "embedding",
"fieldValue": "={{ JSON.stringify($json.data[0].embedding) }}"
},
{
"fieldId": "metadata",
"fieldValue": "={{ $('Merge Context with Chunk').item.json.metadata }}"
}
]
},
"useCustomSchema": true
},
"typeVersion": 1
},
{
"id": "f634d6fa-8fea-42c3-9da2-f11ffea7fdf5",
"name": "Results Found?",
"type": "n8n-nodes-base.if",
"position": [
-4128,
4032
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "b1dbe9f1-c4a4-4dc1-9cda-a3b2a8f9975d",
"operator": {
"type": "array",
"operation": "lengthGt",
"rightType": "number"
},
"leftValue": "={{ $json.results }}",
"rightValue": 0
}
]
}
},
"typeVersion": 2.2
},
{
"id": "9755a7c7-2075-4abd-be4d-24ccc630b2b8",
"name": "Return \"No results found!\" Message",
"type": "n8n-nodes-base.set",
"position": [
-3904,
4128
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "07d89f6c-f1a4-42cf-b440-d4675cb3c919",
"name": "response",
"type": "string",
"value": "No results found!"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "f6b77a55-d518-4189-99c6-e141997b3afa",
"name": "Parse & Extract Data",
"type": "n8n-nodes-base.set",
"position": [
-4848,
3040
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "60bf7681-ca81-428f-aefe-a4a4a78dd8c7",
"name": "chatInput",
"type": "string",
"value": "={{ JSON.parse($json.body.question).conversation.messages[0].content }}"
},
{
"id": "4e7eb309-67b3-49fa-a21d-ee8ebc395396",
"name": "sessionId",
"type": "string",
"value": "={{ $json.body.overrideConfig.sessionId }}"
},
{
"id": "4f7e9ba7-4ca4-440d-9f17-cd71ad489907",
"name": "accountId",
"type": "number",
"value": "={{ JSON.parse($json.body.question).account.id }}"
},
{
"id": "d8232acf-da81-4636-9a1f-e2e0a2fd70cd",
"name": "conversationId",
"type": "number",
"value": "={{ JSON.parse($json.body.question).conversation.id }}"
},
{
"id": "94943b0f-30f0-4336-97fa-c743e410450c",
"name": "event",
"type": "string",
"value": "={{ JSON.parse($json.body.question).event }}"
},
{
"id": "5e39d8df-1c6a-46c4-9ca3-b17a7b5cff39",
"name": "file",
"type": "string",
"value": "={{ $json.body.uploads?.[0]?.data }}"
},
{
"id": "93fd81e1-5347-48bf-ad45-c2b477508a12",
"name": "fileName",
"type": "string",
"value": "={{ $json.body.uploads?.[0]?.name }}"
},
{
"id": "93031ff3-a959-49f9-b54d-486614f7bc67",
"name": "accessToken",
"type": "string",
"value": "Ca5hFni7ELxPio8xqBdQrGjX"
},
{
"id": "a21b1dea-acfc-4b23-8b67-367007845419",
"name": "supabase_schema",
"type": "string",
"value": "ht_rag_chatbot"
},
{
"id": "dd949aee-bc15-4c76-a0cf-17a6dcf81007",
"name": "mimeType",
"type": "string",
"value": "={{ $json.body.uploads[0].mime }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "fde373d2-3f8b-486d-98a5-2b9727241573",
"name": "Filter Events",
"type": "n8n-nodes-base.filter",
"position": [
-4624,
3040
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "062166c3-6d7f-43b1-9ee5-1c2040982959",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.event }}",
"rightValue": "message_created"
}
]
}
},
"typeVersion": 2.3
},
{
"id": "41a8698d-088b-46ea-b58e-f9a9a1289d82",
"name": "Check File Type",
"type": "n8n-nodes-base.set",
"position": [
-3728,
3664
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "4f9af98f-f755-4561-903b-28a4305b1402",
"name": "isImage",
"type": "boolean",
"value": "={{ $('Parse & Extract Data').item.json.file && ($('Parse & Extract Data').item.json.file?.toLowerCase().endsWith('.png') || $('Parse & Extract Data').item.json.file?.toLowerCase().endsWith('.jpg') || $('Parse & Extract Data').item.json.file?.toLowerCase().endsWith('.jpeg') || $('Parse & Extract Data').item.json.file?.toLowerCase().endsWith('.webp')) }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "0dcb70c6-3c54-4029-9446-465c8070b4ce",
"name": "Is Image?",
"type": "n8n-nodes-base.if",
"position": [
-3504,
3664
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "141c82e2-e6ff-4e0f-93eb-ba76b7c216b0",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $json.isImage }}",
"rightValue": true
}
]
}
},
"typeVersion": 2.3
},
{
"id": "f6a06a43-c4d7-40d8-89b8-8cc39ff21c05",
"name": "Analyze Image",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
-3280,
3520
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4o"
},
"options": {
"maxTokens": 300
},
"resource": "image",
"imageUrls": "={{ $('Parse & Extract Data').item.json.file }}",
"operation": "analyze"
},
"typeVersion": 2.1
},
{
"id": "68187a0c-ac7e-4ff2-bc8b-dac11aaa2d9c",
"name": "Send Response",
"type": "n8n-nodes-base.httpRequest",
"position": [
-1952,
3280
],
"parameters": {
"url": "=https://app.omniaichatbot.com/api/v1/accounts/{{ $('Parse & Extract Data').item.json.accountId }}/conversations/{{ $('Parse & Extract Data').item.json.conversationId }}/messages",
"method": "POST",
"options": {},
"sendBody": true,
"sendHeaders": true,
"bodyParameters": {
"parameters": [
{
"name": "content",
"value": "={{ $json.output }}"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "api_access_token",
"value": "={{ $('Parse & Extract Data').item.json.accessToken }}"
}
]
}
},
"typeVersion": 4.3
},
{
"id": "183151bd-791f-42f2-bc8a-8354c52dade5",
"name": "Set 'File Not Supported' Message",
"type": "n8n-nodes-base.set",
"position": [
-3040,
3584
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "f9700991-cab8-405a-86aa-bde574787853",
"name": "output",
"type": "string",
"value": "File not supported"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "793eba29-2047-4a7a-a5b4-1734c050ec55",
"name": "Is File?",
"type": "n8n-nodes-base.if",
"position": [
-4400,
3040
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "d6845299-a43a-4b25-9295-75a8f0218b72",
"operator": {
"type": "string",
"operation": "exists",
"singleValue": true
},
"leftValue": "={{ $json.file }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.3
},
{
"id": "e0390ae1-721e-41b0-abdc-a18f585d46c7",
"name": "When clicking ‘Execute workflow’",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-4128,
2400
],
"parameters": {},
"typeVersion": 1
},
{
"id": "590e08e9-07f9-410c-b37f-ac7398ff220c",
"name": "Set URL to Crawl",
"type": "n8n-nodes-base.set",
"position": [
-3920,
2400
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "5dc85fbc-446b-4a5e-b0d5-59494ea0000b",
"name": "url_to_crawl",
"type": "string",
"value": "https://grecostrom.gr/en/"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "cef5f488-5f76-40aa-a4e8-3388c0ba161a",
"name": "Receive Firecrawl Events",
"type": "n8n-nodes-base.webhook",
"position": [
-4032,
1840
],
"webhookId": "6279f0ee-3daa-4530-9c92-7163923a03cb",
"parameters": {
"path": "firecrawl",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 2.1
},
{
"id": "89d67646-90c1-4a14-a62f-83e1d04221f1",
"name": "Is Webhook Source?",
"type": "n8n-nodes-base.if",
"position": [
-3232,
1472
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "1aa4e642-f519-41f8-b641-016686bc1518",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $('Receive Firecrawl Events').isExecuted }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.3
},
{
"id": "e58b25cb-2af7-44fb-84c1-7f23ac5061bd",
"name": "Encode Markdown to Base64",
"type": "n8n-nodes-base.code",
"position": [
-2784,
1376
],
"parameters": {
"jsCode": "\nfor (const item of $input.all()) {\n\n item.json.encoded_message =\n Buffer.from($input.first().json.body.data[0].markdown).toString('base64');\n\n}\n\nreturn $input.all();"
},
"typeVersion": 2
},
{
"id": "f0fd858b-6ffb-429a-a122-0e0121baabaf",
"name": "Convert Markdown to Binary",
"type": "n8n-nodes-base.convertToFile",
"position": [
-2560,
1376
],
"parameters": {
"options": {},
"operation": "toBinary",
"sourceProperty": "encoded_message"
},
"typeVersion": 1.1
},
{
"id": "2412a867-3164-422d-99a6-012ec6d34e07",
"name": "Has Markdown Content?",
"type": "n8n-nodes-base.if",
"position": [
-3008,
1376
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "dd82251d-b715-41b6-b68f-39be664d9780",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{ $json.body.data[0].markdown }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.3
},
{
"id": "676fa4cd-0cd9-469d-8007-886b1a8d1096",
"name": "Configure Settings",
"type": "n8n-nodes-base.set",
"position": [
-3456,
1472
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "e81c34b5-10d3-4e9c-b152-064ed252bd44",
"name": "supabase_url",
"type": "string",
"value": "https://hpschyruavrtmhgbwcur.supabase.co"
},
{
"id": "a835f7c8-2bbc-4a31-a1ce-7c07ac4f3152",
"name": "images_bucket_name",
"type": "string",
"value": "leo_rag_pdf_images"
},
{
"id": "6c3e89e2-bc03-4fb1-bbcc-2d3b683d2314",
"name": "schema",
"type": "string",
"value": "ht_rag_chatbot"
},
{
"id": "212c26a9-eb9a-4b8f-a6c6-5174766d2281",
"name": "file_id",
"type": "string",
"value": "={{ $json.id || $json.body.data[0].metadata.url }}"
},
{
"id": "2a407d15-d00d-4ed4-98d7-2c82b9d9943d",
"name": "title",
"type": "string",
"value": "={{ $('Receive Firecrawl Events').isExecuted ? $json.body.data[0].metadata.title : $json.name}}"
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "9b9e8fd7-e162-43b6-9ae6-5879b265a385",
"name": "Check MIME Type",
"type": "n8n-nodes-base.switch",
"position": [
-992,
1472
],
"parameters": {
"rules": {
"values": [
{
"outputKey": "Unstructured",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "or",
"conditions": [
{
"id": "29bcc41f-d0ec-44e0-9a1a-25a1a6c4149d",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "application/pdf"
},
{
"id": "27063ae6-827d-4c1f-8890-4eb1314be054",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "application/vnd.google-apps.document"
},
{
"id": "180e96eb-a7c5-49cb-b518-b5708915d366",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
},
{
"id": "f21c758b-4777-49fe-a641-3f8c2871b0d0",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "application/msword"
},
{
"id": "e14b9c37-ad21-48e4-a083-d918578bf7ea",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "text/rtf"
},
{
"id": "cde662cf-f128-4607-af50-1c991f69297a",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "application/vnd.oasis.opendocument.text"
},
{
"id": "5d5e6d56-cd46-49ae-95fe-87bbf610400f",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "application/vnd.openxmlformats-officedocument.presentationml.presentation"
},
{
"id": "b4734f23-679d-4382-86fd-07fb912eed10",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "application/vnd.ms-powerpoint"
},
{
"id": "32d1f0a6-7f96-4e24-bb94-992341d1cc99",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "text/plain"
},
{
"id": "cfd83d08-4af2-49ed-9114-984c2346b668",
"operator": {
"type": "string",
"operation": "contains"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "markdown"
},
{
"id": "NEW_ID_HERE",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $('Receive Firecrawl Events').isExecuted }}",
"rightValue": ""
}
]
},
"renameOutput": true
},
{
"outputKey": "Tabular",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "or",
"conditions": [
{
"id": "86015eca-4f4f-4dbe-a27c-7d15354510db",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "application/vnd.ms-excel"
},
{
"id": "f0661b47-b06a-41af-af3d-f87a2dce77de",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
},
{
"id": "874d98e3-ffed-4084-b695-ca38e50dbb3d",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "text/csv"
},
{
"id": "00b84f0c-fb43-4417-a905-81d161f03fde",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Batch Process Files').item.json.mimeType }}",
"rightValue": "application/vnd.google-apps.spreadsheet"
}
]
},
"renameOutput": true
}
]
},
"options": {}
},
"typeVersion": 3.2
},
{
"id": "7ea2c2b7-1fbd-4b7b-948b-68c361d1d726",
"name": "Is Webhook Source? (Post-Hash)",
"type": "n8n-nodes-base.if",
"position": [
-96,
1472
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "0a8005c2-b1df-4f5e-825e-4f0987327ee9",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $('Receive Firecrawl Events').isExecuted }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.3
},
{
"id": "ac0e2b72-7870-4f85-bce5-a15018b354ed",
"name": "Encode Webhook Markdown to Base64",
"type": "n8n-nodes-base.code",
"position": [
144,
1856
],
"parameters": {
"jsCode": "\nfor (const item of $input.all()) {\n\n item.json.encoded_message =\n Buffer.from($('Batch Process Files').first().json.body.data[0].markdown).toString('base64');\n\n}\n\nreturn $input.all();"
},
"typeVersion": 2
},
{
"id": "1bf0fba6-0935-4c90-8986-4724bdee0610",
"name": "Convert Webhook Markdown to Binary",
"type": "n8n-nodes-base.convertToFile",
"position": [
320,
1856
],
"parameters": {
"options": {},
"operation": "toBinary",
"sourceProperty": "encoded_message"
},
"typeVersion": 1.1
},
{
"id": "ffed29e7-a19a-4ff8-aac2-914b79d5f4fc",
"name": "Filter Google Drive Files",
"type": "n8n-nodes-base.filter",
"position": [
-3920,
672
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "b8db986c-4f90-480a-9eea-392d46088ffe",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.record_type }}",
"rightValue": "google_drive_file"
}
]
}
},
"typeVersion": 2.3
},
{
"id": "7b6406be-46d9-4bd8-bef7-dca38db819b0",
"name": "Start Firecrawl Crawl",
"type": "n8n-nodes-base.httpRequest",
"position": [
-3728,
2400
],
"parameters": {
"url": "https://api.firecrawl.dev/v2/crawl",
"method": "POST",
"options": {},
"jsonBody": "={\n \"url\": \"{{ $json.url_to_crawl }}\",\n \"sitemap\": \"skip\",\n \"crawlEntireDomain\": true,\n \"webhook\": {\n \"events\" : [\n \"page\"\n ],\n \"url\": \"https://n8n.hellenictechnologies.com/webhook/firecrawl\"\n },\n \"limit\": 20,\n \"excludePaths\": [\n \"/wp-admin/*\",\n \"/wp-login/*\",\n \"/admin/*\",\n \"/cart/*\",\n \"/checkout/*\",\n \"/account/*\",\n \"/login/*\",\n \"/register/*\",\n \"/signup/*\",\n \"/my-account/*\",\n \"/privacy*\",\n \"/terms*\",\n \"/cookie*\",\n \"/legal/*\",\n \"/search*\",\n \"/feed/*\",\n \"/xmlrpc*\",\n \"/wp-json/*\",\n \"/tag/*\",\n \"/tags/*\",\n \"/author/*\",\n \"/date/*\",\n \"/page/*\",\n \"/category/*\",\n \"/wp-content/*\",\n \"/wp-includes/*\",\n \"/cdn-cgi/*\",\n \"/print/*\",\n \"/share/*\",\n \"/embed/*\"\n ],\n \"maxDiscoveryDepth\": 3,\n \"scrapeOptions\": {\n \"onlyMainContent\": true,\n \"excludeTags\": [\n \"nav\",\n \"footer\",\n \"header\",\n \"aside\",\n \"form\",\n \"button\",\n \"script\",\n \"style\",\n \"noscript\",\n \"iframe\"\n ],\n \"maxAge\": 172800000,\n \"parsers\": [\n \"pdf\"\n ],\n \"formats\": [\n \"markdown\"\n ]\n }\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"typeVersion": 4.3
},
{
"id": "8f807345-0060-4da0-8b81-5295bfe328c7",
"name": "Process Chat File Upload",
"type": "n8n-nodes-base.code",
"position": [
-4176,
3216
],
"parameters": {
"jsCode": "// Get all input items (could be multiple files)\nconst items = $input.all();\n\nconst results = items.map(item => {\n const dataUri = item.json.file; // The base64 data URI\n const webhookMimeType = item.json.mimeType; // The mime type\n const webhookFileName = item.json.fileName; // The actual filename\n \n // Check if dataUri exists\n if (!dataUri) {\n throw new Error('No file field found in input');\n }\n \n // If mimeType is null, keep everything as null and return early\n if (webhookMimeType === null || webhookMimeType === undefined) {\n const base64Data = dataUri.includes(',') ? dataUri.split(',')[1] : dataUri;\n \n return {\n json: {\n fileName: webhookFileName || 'uploaded-document',\n mimeType: null\n },\n binary: {\n data: {\n data: base64Data,\n mimeType: null,\n fileName: webhookFileName || 'uploaded-document'\n }\n }\n };\n }\n \n // Split to get the base64 part (after the comma)\n const base64Data = dataUri.includes(',') ? dataUri.split(',')[1] : dataUri;\n \n // Determine MIME type - prioritize file extension over webhook mime\n let actualMimeType = webhookMimeType || 'application/octet-stream';\n let fileName = webhookFileName || 'uploaded-document';\n \n // Extract extension from filename\n const fileExtension = fileName.includes('.') ? fileName.split('.').pop().toLowerCase() : '';\n \n // Map extension to proper MIME type\n const mimeTypeMap = {\n 'csv': 'text/csv',\n 'pdf': 'application/pdf',\n 'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n 'doc': 'application/msword',\n 'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n 'xls': 'application/vnd.ms-excel',\n 'pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',\n 'ppt': 'application/vnd.ms-powerpoint',\n 'txt': 'text/plain',\n 'md': 'text/markdown',\n 'rtf': 'application/rtf',\n 'odt': 'application/vnd.oasis.opendocument.text',\n 'json': 'application/json',\n 'html': 'text/html',\n 'htm': 'text/html',\n 'jpg': 'image/jpeg',\n 'jpeg': 'image/jpeg',\n 'gif': 'image/gif',\n 'webp': 'image/webp'\n };\n \n // Override mime type if we can detect from extension\n if (fileExtension && mimeTypeMap[fileExtension]) {\n actualMimeType = mimeTypeMap[fileExtension];\n }\n \n // Create binary data object for n8n\n return {\n json: {\n fileName: fileName,\n mimeType: actualMimeType\n },\n binary: {\n data: {\n data: base64Data,\n mimeType: actualMimeType,\n fileName: fileName\n }\n }\n };\n});\n\nreturn results;"
},
"typeVersion": 2
},
{
"id": "b1728da2-9f63-433b-9191-a078f14292b6",
"name": "Chat Message",
"type": "n8n-nodes-base.webhook",
"position": [
-5072,
3040
],
"webhookId": "9041bbed-b80e-46fa-88ed-412366730e4d",
"parameters": {
"path": "rag-chatbot",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 2.1
},
{
"id": "9be2c46b-bb30-42bf-8214-0dd8ec386b13",
"name": "Convert File",
"type": "@mazix/n8n-nodes-converter-documents.convertFileToJson",
"position": [
-3504,
3328
],
"parameters": {
"maxFileSize": 10,
"maxConcurrency": 1
},
"executeOnce": false,
"retryOnFail": false,
"typeVersion": 5
},
{
"id": "eeff43ce-2554-457a-b13c-a5a378437307",
"name": "Prepare Agent Input",
"type": "n8n-nodes-base.set",
"position": [
-3040,
2928
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "a9df9317-1951-4015-8e8e-27490419fbfa",
"name": "chatInput",
"type": "string",
"value": "={{ $json.chatInput || $json.markdown || $json.text || $json['0'].content[0].text}}"
},
{
"id": "643baae2-171b-4268-945e-1d8105c51e74",
"name": "sessionId",
"type": "string",
"value": "={{ $('Parse & Extract Data').item.json.sessionId }}"
},
{
"id": "7ac9d706-d51f-4b96-99e5-db17a0c2091d",
"name": "isFile",
"type": "string",
"value": "={{ $('Parse & Extract Data').first().json.file ? true : false }}"
},
{
"id": "39f7e2f8-0bb5-4137-ba7e-61c5ba54530d",
"name": "isImage",
"type": "boolean",
"value": "={{ $('Is Image?').isExecuted ? true : false }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "e02bf757-441b-43c1-ba3b-cef6ad261a2a",
"name": "Format Files for Chat Input",
"type": "n8n-nodes-base.code",
"position": [
-3280,
3328
],
"parameters": {
"jsCode": "const items = $input.all();\n\nreturn items.map(item => {\n const files = item.json.files || [];\n const totalFiles = item.json.totalFiles || 0;\n \n // Build consolidated message for each file\n const fileMessages = files.map(file => {\n const metadata = file.metadata || {};\n let content = '';\n \n // Check if file has sheets (tabular data like XLSX, XLS, CSV)\n if (file.sheets) {\n const sheetNames = Object.keys(file.sheets);\n \n content += `Tabular Data (${sheetNames.length} sheet${sheetNames.length > 1 ? 's' : ''}):\\n\\n`;\n \n sheetNames.forEach(sheetName => {\n const rows = file.sheets[sheetName];\n content += `Sheet: ${sheetName}\\n`;\n content += `Rows: ${rows.length}\\n`;\n \n // Convert to markdown table format\n if (rows.length > 0) {\n const headers = Object.keys(rows[0]);\n \n // Table header\n content += `| ${headers.join(' | ')} |\\n`;\n content += `| ${headers.map(() => '---').join(' | ')} |\\n`;\n \n // Table rows (limit to first 10 rows for readability)\n const rowLimit = Math.min(rows.length, 10);\n for (let i = 0; i < rowLimit; i++) {\n const row = rows[i];\n const values = headers.map(h => row[h] !== undefined ? row[h] : '');\n content += `| ${values.join(' | ')} |\\n`;\n }\n \n if (rows.length > 10) {\n content += `\\n... and ${rows.length - 10} more rows\\n`;\n }\n }\n \n content += '\\n';\n });\n } \n // Check if file has text content (documents like PDF, DOCX, etc)\n else if (file.text) {\n content = `Text Content:\\n${file.text}`;\n } else {\n content = 'No content extracted';\n }\n \n return `File Analysis\n\nFile Details:\n- Name: ${metadata.fileName || 'Unknown'}\n- Type: ${metadata.fileType ? metadata.fileType.toUpperCase() : 'Unknown'}\n- Size: ${metadata.fileSize ? (metadata.fileSize / 1024).toFixed(2) + ' KB' : 'Unknown'}\n- Processed: ${metadata.processedAt ? new Date(metadata.processedAt).toLocaleString() : 'Unknown'}\n\n${content}`;\n }).join('\\n\\n---\\n\\n');\n \n // Create final chat input\n const chatInput = totalFiles > 1 \n ? `User uploaded ${totalFiles} files:\\n\\n${fileMessages}`\n : fileMessages;\n \n return {\n json: {\n chatInput: chatInput,\n is_file: true\n }\n };\n});"
},
"typeVersion": 2
},
{
"id": "57cbc53d-56ae-4e8d-a500-14e313cca844",
"name": "Route Chat Upload by Type",
"type": "n8n-nodes-base.switch",
"position": [
-3952,
3024
],
"parameters": {
"rules": {
"values": [
{
"outputKey": "PDF",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "fdd3d7f5-c54b-41be-8c51-b2e2e9608e82",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.mimeType }}",
"rightValue": "=application/pdf"
}
]
},
"renameOutput": true
},
{
"outputKey": "DOCX",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "98339dcd-3d32-4301-89e8-a8253b2ee5e6",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.mimeType }}",
"rightValue": "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
}
]
},
"renameOutput": true
},
{
"outputKey": "DOC",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "1eb632fb-11cf-4030-b852-7949411760b3",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.mimeType }}",
"rightValue": "application/msword"
}
]
},
"renameOutput": true
},
{
"outputKey": "RTF",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "a9d8a4c3-621d-4793-971f-c7d4195bacb6",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ [\"text/rtf\", \"application/rtf\"].includes($json.mimeType) }}",
"rightValue": "="
}
]
},
"renameOutput": true
},
{
"outputKey": "ODT",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "62d9a39d-1a0a-4308-88e2-5037896e3322",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.mimeType }}",
"rightValue": "application/vnd.oasis.opendocument.text"
}
]
},
"renameOutput": true
},
{
"outputKey": "PPTX",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "c37ff00f-1777-403b-808a-aa7224c7e92a",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.mimeType }}",
"rightValue": "application/vnd.openxmlformats-officedocument.presentationml.presentation"
}
]
},
"renameOutput": true
},
{
"outputKey": "PPT",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "39254a94-bfd6-4d89-ae1e-5ffa6f88a313",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.mimeType }}",
"rightValue": "application/vnd.ms-powerpoint"
}
]
},
"renameOutput": true
},
{
"outputKey": "TXT",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "10171128-3096-4715-b4af-65ba8e3e9622",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.mimeType }}",
"rightValue": "text/plain"
}
]
},
"renameOutput": true
},
{
"outputKey": "JSON",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "66dad435-1692-44a1-82e7-a8265fd02ad0",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.mimeType }}",
"rightValue": "application/json"
}
]
},
"renameOutput": true
},
{
"outputKey": "MD",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "4072555c-a5c8-42db-866f-627832cfb96f",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.mimeType }}",
"rightValue": "text/x-markdown"
}
]
},
"renameOutput": true
},
{
"outputKey": "CSV",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "84139a61-d41f-401a-b622-63dc2eede11d",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.mimeType }}",
"rightValue": "text/csv"
}
]
},
"renameOutput": true
},
{
"outputKey": "XLSX",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "2b85801c-9412-4e0f-b3e1-10a64cb93b20",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.mimeType }}",
"rightValue": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
}
]
},
"renameOutput": true
},
{
"outputKey": "XLS",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "042b4f32-1d14-4aa7-b944-0b6a33a7f2a3",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.mimeType }}",
"rightValue": "application/vnd.ms-excel"
}
]
},
"renameOutput": true
},
{
"outputKey": "NULL",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "f2abf1d7-47ba-4563-93b2-3109c453fe5a",
"operator": {
"type": "string",
"operation": "notExists",
"singleValue": true
},
"leftValue": "={{ $json.mimeType }}",
"rightValue": ""
}
]
},
"renameOutput": true
}
]
},
"options": {}
},
"typeVersion": 3.3
},
{
"id": "063e2e42-9d3a-4f0e-a945-d1f416c37c48",
"name": "Extract PDF Content (Chat)",
"type": "n8n-nodes-base.extractFromFile",
"position": [
-3456,
2976
],
"parameters": {
"options": {},
"operation": "pdf"
},
"typeVersion": 1.1
},
{
"id": "ec8a9152-dc82-4e7c-adbe-3f3553172e3e",
"name": "Set File Unsupported Response",
"type": "n8n-nodes-base.set",
"position": [
-3040,
3232
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "27ae9776-9c5a-407d-91dd-8c9e661583ad",
"name": "output",
"type": "string",
"value": "File not supported"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "3e4ee6ee-74f2-483a-a446-f71148abae13",
"name": "Schedule File Sync (Every 15Min)",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-5040,
768
],
"parameters": {
"rule": {
"interval": [
{
"field": "minutes",
"minutesInterval": 15
}
]
}
},
"typeVersion": 1.3
},
{
"id": "3582696d-7b2d-4dc3-bcaa-3d2dad3fa186",
"name": "Insert CSV Tabular Row",
"type": "n8n-nodes-base.supabase",
"position": [
3424,
1376
],
"parameters": {
"schema": "={{ $('Configure Settings').item.json.schema }}",
"tableId": "tabular_document_rows",
"fieldsUi": {
"fieldValues": [
{
"fieldId": "record_manager_id",
"fieldValue": "={{ $('Set Hash Record Id').item.json.hash_record_id }}"
},
{
"fieldId": "row_data",
"fieldValue": "={{ $json }}"
},
{
"fieldId": "sheet_id",
"fieldValue": "={{ $('Add CSV Sheet Row').item.json.id }}"
}
]
},
"useCustomSchema": true
},
"retryOnFail": true,
"typeVersion": 1,
"waitBetweenTries": 5000
},
{
"id": "d3a8013c-0651-4f10-8dfe-ea438f7c461b",
"name": "Split CSV Data Rows",
"type": "n8n-nodes-base.splitOut",
"position": [
3200,
1376
],
"parameters": {
"options": {},
"fieldToSplitOut": "data_rows"
},
"typeVersion": 1
},
{
"id": "af4c3559-0c7c-4ab4-847f-346b00a740e5",
"name": "Wait for CSV Schema Update",
"type": "n8n-nodes-base.merge",
"position": [
2688,
1376
],
"parameters": {
"mode": "combine",
"options": {},
"combineBy": "combineAll"
},
"typeVersion": 3.2
},
{
"id": "81d9d3d7-7106-4a38-be17-be7a7169afd6",
"name": "Set CSV Text for Embedding",
"type": "n8n-nodes-base.set",
"position": [
2976,
1376
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "7bf3ca0d-5221-4bab-b33a-d59be30d49a6",
"name": "text",
"type": "string",
"value": "={{ $('Wait for CSV Schema Update').item.json.concatenated_data }}"
},
{
"id": "7c35e7e6-94ba-44f2-999b-d89092dd353f",
"name": "data_rows",
"type": "array",
"value": "={{ $('Aggregate CSV Rows').item.json.data }}"
}
]
}
},
"executeOnce": true,
"typeVersion": 3.4
},
{
"id": "b1e27133-24bb-48d1-a952-9d5160ea811e",
"name": "Concatenate CSV Data",
"type": "n8n-nodes-base.summarize",
"position": [
2400,
1472
],
"parameters": {
"options": {},
"fieldsToSummarize": {
"values": [
{
"field": "data",
"aggregation": "concatenate"
}
]
}
},
"typeVersion": 1.1
},
{
"id": "d8c8573d-f10f-4636-8a51-a98adb56e16e",
"name": "Add CSV Sheet Row",
"type": "n8n-nodes-base.supabase",
"position": [
2400,
1280
],
"parameters": {
"schema": "={{ $('Configure Settings').item.json.schema }}",
"tableId": "tabular_document_sheets",
"fieldsUi": {
"fieldValues": [
{
"fieldId": "schema",
"fieldValue": "={{$json.data.first().keys()}}"
},
{
"fieldId": "record_manager_id",
"fieldValue": "={{ $('Set Hash Record Id').item.json.hash_record_id }}"
},
{
"fieldId": "metadata",
"fieldValue": "={{ $json.metadata }}"
}
]
},
"useCustomSchema": true
},
"executeOnce": true,
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "b86369d4-3c22-4769-8a26-77942838ef37",
"name": "Aggregate CSV Rows",
"type": "n8n-nodes-base.aggregate",
"position": [
1952,
1376
],
"parameters": {
"options": {},
"aggregate": "aggregateAllItemData"
},
"typeVersion": 1
},
{
"id": "b352bbc4-1142-4c40-98d6-0a15d4034d85",
"name": "Extract CSV Data",
"type": "n8n-nodes-base.extractFromFile",
"position": [
1728,
1376
],
"parameters": {
"options": {}
},
"typeVersion": 1.1
},
{
"id": "c347bd6a-c9cf-4d5c-b9d3-fe619c14436b",
"name": "Analyze CSV Column Metadata",
"type": "n8n-nodes-base.code",
"position": [
2176,
1376
],
"parameters": {
"jsCode": "const data = $json.data || [];\n\n if (data.length === 0) {\n return { json: { data, metadata: null } };\n }\n\n // Sample rows (first 3, exactly as stored)\n const sample_rows = data.slice(0, 3);\n\n // Analyze columns\n const columns = {};\n const keys = Object.keys(data[0] || {});\n\n for (const key of keys) {\n const values = data.map(row => row[key]);\n const nonEmpty = values.filter(v => v != null && v !== '');\n const uniqueValues = [...new Set(nonEmpty)];\n\n columns[key] = {\n sample_values: uniqueValues.slice(0, 5),\n unique_count: uniqueValues.length,\n null_count: values.length - nonEmpty.length,\n all_numeric: nonEmpty.length > 0 && nonEmpty.every(v => !isNaN(parseFloat(v)))\n };\n }\n\n return {\n json: {\n data,\n metadata: {\n row_count: data.length,\n sample_rows,\n columns\n }\n }\n };"
},
"typeVersion": 2
},
{
"id": "5eee0c24-db1c-4e96-b56d-5d516d158893",
"name": "Extract Sheets",
"type": "n8n-nodes-base.code",
"position": [
576,
1888
],
"parameters": {
"jsCode": "const XLSX = require('xlsx');\n\n // Get the binary data from previous node (e.g., from HTTP Request or Read Binary File)\n const binaryData = await this.helpers.getBinaryDataBuffer(0, 'data');\n\n // Parse the workbook\n const workbook = XLSX.read(binaryData, { type: 'buffer' });\n\n // Get all sheet names\n const sheetNames = workbook.SheetNames;\n\n // Process each sheet\n const results = [];\n for (const sheetName of sheetNames) {\n const worksheet = workbook.Sheets[sheetName];\n const jsonData = XLSX.utils.sheet_to_json(worksheet);\n\n results.push({\n sheetName: sheetName,\n data: jsonData\n });\n }\n\n return results.map(r => ({ json: r }));"
},
"typeVersion": 2
},
{
"id": "97e50cc5-56dd-4f9d-b44b-cd8f0963042e",
"name": "Add Sheet Row1",
"type": "n8n-nodes-base.supabase",
"position": [
1248,
1792
],
"parameters": {
"schema": "={{ $('Configure Settings').item.json.schema }}",
"tableId": "tabular_document_sheets",
"fieldsUi": {
"fieldValues": [
{
"fieldId": "schema",
"fieldValue": "={{$json.data.first().keys()}}"
},
{
"fieldId": "record_manager_id",
"fieldValue": "={{ $('Set Hash Record Id').item.json.hash_record_id }}"
},
{
"fieldId": "sheet_name",
"fieldValue": "={{ $('Loops Over Sheets1').item.json.sheetName || null }}"
},
{
"fieldId": "metadata",
"fieldValue": "={{ $json.metadata }}"
}
]
},
"useCustomSchema": true
},
"executeOnce": true,
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "78bb10db-9626-4980-ad9b-7c42ca8db5da",
"name": "Loops Over Sheets1",
"type": "n8n-nodes-base.splitInBatches",
"position": [
800,
1888
],
"parameters": {
"options": {},
"batchSize": 3
},
"typeVersion": 3
},
{
"id": "142ac654-da60-4ee1-adac-8a51bd619c1e",
"name": "Insert Tabular Row1",
"type": "n8n-nodes-base.supabase",
"position": [
2144,
1888
],
"parameters": {
"schema": "={{ $('Configure Settings').item.json.schema }}",
"tableId": "tabular_document_rows",
"fieldsUi": {
"fieldValues": [
{
"fieldId": "record_manager_id",
"fieldValue": "={{ $('Set Hash Record Id').item.json.hash_record_id }}"
},
{
"fieldId": "row_data",
"fieldValue": "={{ $json }}"
},
{
"fieldId": "sheet_id",
"fieldValue": "={{ $('Add Sheet Row1').item.json.id }}"
}
]
},
"useCustomSchema": true
},
"retryOnFail": true,
"typeVersion": 1,
"waitBetweenTries": 5000
},
{
"id": "361dbf53-5918-4330-bfd4-21da35ae55a2",
"name": "Split Data Rows1",
"type": "n8n-nodes-base.splitOut",
"position": [
1920,
1888
],
"parameters": {
"options": {},
"fieldToSplitOut": "data_rows"
},
"typeVersion": 1
},
{
"id": "4e9fa4c9-5ae3-4a04-9271-017a7f697884",
"name": "Wait for Schema Update1",
"type": "n8n-nodes-base.merge",
"position": [
1472,
1888
],
"parameters": {
"mode": "combine",
"options": {},
"combineBy": "combineAll"
},
"typeVersion": 3.2
},
{
"id": "af74c5a3-254b-4518-bc05-d8ade58bc295",
"name": "Set Text for Tabular Data1",
"type": "n8n-nodes-base.set",
"position": [
1696,
1888
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "7bf3ca0d-5221-4bab-b33a-d59be30d49a6",
"name": "text",
"type": "string",
"value": "={{ $('Wait for Schema Update1').item.json.concatenated_data }}"
},
{
"id": "7c35e7e6-94ba-44f2-999b-d89092dd353f",
"name": "data_rows",
"type": "array",
"value": "={{ $('Loops Over Sheets1').item.json.data || null}}"
}
]
}
},
"executeOnce": true,
"typeVersion": 3.4
},
{
"id": "db2a4f25-5e2a-4986-99ee-da0fb7bf4d15",
"name": "Concatenate Tabular Data1",
"type": "n8n-nodes-base.summarize",
"position": [
1248,
1984
],
"parameters": {
"options": {},
"fieldsToSummarize": {
"values": [
{
"field": "data",
"aggregation": "concatenate"
}
]
}
},
"typeVersion": 1.1
},
{
"id": "e985cb5b-3824-4701-a5cb-4d8769fc2e55",
"name": "Analyze Sheet Column Metadata1",
"type": "n8n-nodes-base.code",
"position": [
1024,
1888
],
"parameters": {
"jsCode": "const data = $json.data || [];\n\n if (data.length === 0) {\n return { json: { data, metadata: null } };\n }\n\n // Sample rows (first 3, exactly as stored)\n const sample_rows = data.slice(0, 3);\n\n // Analyze columns\n const columns = {};\n const keys = Object.keys(data[0] || {});\n\n for (const key of keys) {\n const values = data.map(row => row[key]);\n const nonEmpty = values.filter(v => v != null && v !== '');\n const uniqueValues = [...new Set(nonEmpty)];\n\n columns[key] = {\n sample_values: uniqueValues.slice(0, 5),\n unique_count: uniqueValues.length,\n null_count: values.length - nonEmpty.length,\n all_numeric: nonEmpty.length > 0 && nonEmpty.every(v => !isNaN(parseFloat(v)))\n };\n }\n\n return {\n json: {\n data,\n metadata: {\n row_count: data.length,\n sample_rows,\n columns\n }\n }\n };"
},
"typeVersion": 2
},
{
"id": "1ff81322-78b4-4ba8-8b28-8e16830a8dd4",
"name": "CSV Prepare LLM Prompt",
"type": "n8n-nodes-base.code",
"position": [
3648,
1376
],
"parameters": {
"jsCode": "// Prepare prompt for LLM to describe the CSV table\nconst metadata = $('Analyze CSV Column Metadata').item.json.metadata;\nconst fileTitle = $('Configure Settings').item.json.title || 'Untitled CSV';\n\n// Get column info (limit to 20)\nconst columnNames = Object.keys(metadata.columns || {}).slice(0, 20);\nconst columnInfo = columnNames.map(col => {\n const info = metadata.columns[col];\n const type = info.all_numeric ? 'numeric' : 'text';\n const samples = info.sample_values.slice(0, 3).join(', ');\n return `- ${col} (${type}): ${samples}`;\n}).join('\\n');\n\n// Get sample rows (limit to 5)\nconst sampleRows = metadata.sample_rows.slice(0, 5);\nconst sampleData = JSON.stringify(sampleRows, null, 2);\n\nconst prompt = `Analyze this tabular dataset and provide a brief 1-2 sentence description of what this data contains and what it could be used for.\n\nFile: ${fileTitle}\nRow count: ${metadata.row_count}\n\nColumns:\n${columnInfo}\n\nSample rows:\n${sampleData}\n\nRespond with ONLY the description, no preamble.`;\n\nreturn { json: { prompt, columnNames } };"
},
"executeOnce": true,
"typeVersion": 2
},
{
"id": "be6ea3f7-a3cd-4e1f-9192-48537b4d55c5",
"name": "CSV Generate Description",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
3872,
1376
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini",
"cachedResultName": "GPT-4O-MINI"
},
"options": {},
"messages": {
"values": [
{
"content": "={{ $json.prompt }}"
}
]
}
},
"retryOnFail": true,
"typeVersion": 1.8,
"waitBetweenTries": 5000
},
{
"id": "92b48b29-83eb-435a-b8ec-233bf8676cd0",
"name": "CSV Build Pointer Content",
"type": "n8n-nodes-base.code",
"position": [
4224,
1376
],
"parameters": {
"jsCode": "// Build pointer content with LLM description\nconst sheetRow = $('Add CSV Sheet Row').first().json;\nconst metadata = $('Analyze CSV Column Metadata').first().json.metadata;\nconst fileTitle = $('Configure Settings').first().json.title || 'Untitled CSV';\nconst fileId = $('Configure Settings').first().json.file_id;\nconst columnNames = $('CSV Prepare LLM Prompt').first().json.columnNames;\n\n// Get LLM description (OpenAI node outputs message.content)\nconst llmResponse = $json.message?.content || $json.content || 'Tabular dataset';\nconst description = llmResponse.trim();\n\n// Build compact column list\nconst columnList = columnNames.map(col => {\n const colInfo = metadata.columns[col];\n return colInfo.all_numeric ? `${col} (num)` : col;\n}).join(', ');\n\n// Build content WITH description\nconst content = `${description}\\n\\nDataset: ${fileTitle}\\nType: CSV\\nRows: ${metadata.row_count}\\nColumns: ${columnList}`;\n\nreturn {\n json: {\n content,\n description,\n sheet_id: sheetRow.id,\n record_manager_id: $('Set Hash Record Id').first().json.hash_record_id,\n metadata: {\n type: 'tabular',\n file_id: fileId,\n sheet_id: sheetRow.id,\n row_count: metadata.row_count,\n columns: columnNames,\n description: description\n }\n }\n};"
},
"executeOnce": true,
"typeVersion": 2
},
{
"id": "a0694338-63fe-4ee2-b2a1-b070c5020349",
"name": "CSV Generate Pointer Embedding",
"type": "n8n-nodes-base.httpRequest",
"position": [
4448,
1376
],
"parameters": {
"url": "https://api.openai.com/v1/embeddings",
"method": "POST",
"options": {},
"jsonBody": "={\n \"input\": {{ JSON.stringify($json.content) }},\n \"model\": \"text-embedding-3-small\"\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "openAiApi"
},
"typeVersion": 4.2
},
{
"id": "ec079b2d-ab30-4922-a5c2-5f417504d5f5",
"name": "CSV Insert Pointer to Documents Hybrid",
"type": "n8n-nodes-base.supabase",
"position": [
4672,
1376
],
"parameters": {
"schema": "={{ $('Configure Settings').first().json.schema }}",
"tableId": "documents_hybrid",
"fieldsUi": {
"fieldValues": [
{
"fieldId": "content",
"fieldValue": "={{ $('CSV Build Pointer Content').item.json.content }}"
},
{
"fieldId": "embedding",
"fieldValue": "={{ JSON.stringify($json.data[0].embedding) }}"
},
{
"fieldId": "metadata",
"fieldValue": "={{ $('CSV Build Pointer Content').item.json.metadata }}"
},
{
"fieldId": "record_manager_id",
"fieldValue": "={{ $('CSV Build Pointer Content').item.json.record_manager_id }}"
},
{
"fieldId": "sheet_id",
"fieldValue": "={{ $('CSV Build Pointer Content').item.json.sheet_id }}"
}
]
},
"useCustomSchema": true
},
"typeVersion": 1
},
{
"id": "c1457b4d-e9a4-4445-9cb9-f4a20db98888",
"name": "XLSX Prepare LLM Prompt",
"type": "n8n-nodes-base.code",
"position": [
2368,
1888
],
"parameters": {
"jsCode": "// Prepare prompt for LLM to describe the XLSX table\nconst metadata = $('Analyze Sheet Column Metadata1').item.json.metadata;\nconst sheetName = $('Loops Over Sheets1').item.json.sheetName || 'Sheet';\nconst fileTitle = $('Configure Settings').item.json.title || 'Untitled Spreadsheet';\n\n// Get column info (limit to 20)\nconst columnNames = Object.keys(metadata.columns || {}).slice(0, 20);\nconst columnInfo = columnNames.map(col => {\n const info = metadata.columns[col];\n const type = info.all_numeric ? 'numeric' : 'text';\n const samples = info.sample_values.slice(0, 3).join(', ');\n return `- ${col} (${type}): ${samples}`;\n}).join('\\n');\n\n// Get sample rows (limit to 5)\nconst sampleRows = metadata.sample_rows.slice(0, 5);\nconst sampleData = JSON.stringify(sampleRows, null, 2);\n\nconst prompt = `Analyze this tabular dataset and provide a brief 1-2 sentence description of what this data contains and what it could be used for.\n\nFile: ${fileTitle}\nSheet: ${sheetName}\nRow count: ${metadata.row_count}\n\nColumns:\n${columnInfo}\n\nSample rows:\n${sampleData}\n\nRespond with ONLY the description, no preamble.`;\n\nreturn { json: { prompt, columnNames, sheetName } };"
},
"executeOnce": true,
"typeVersion": 2
},
{
"id": "23c3d728-ce2f-4091-9be0-37c77fc750cf",
"name": "XLSX Generate Description",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
2592,
1888
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini",
"cachedResultName": "GPT-4O-MINI"
},
"options": {},
"messages": {
"values": [
{
"content": "={{ $json.prompt }}"
}
]
}
},
"retryOnFail": true,
"typeVersion": 1.8,
"waitBetweenTries": 5000
},
{
"id": "ea632ab7-f0bc-48e0-9c05-33b435db01e0",
"name": "XLSX Build Pointer Content",
"type": "n8n-nodes-base.code",
"position": [
2944,
1888
],
"parameters": {
"jsCode": "// Build pointer content with LLM description\nconst sheetRow = $('Add Sheet Row1').first().json;\nconst metadata = $('Analyze Sheet Column Metadata1').first().json.metadata;\nconst fileTitle = $('Configure Settings').first().json.title || 'Untitled Spreadsheet';\nconst fileId = $('Configure Settings').first().json.file_id;\nconst columnNames = $('XLSX Prepare LLM Prompt').first().json.columnNames;\nconst sheetName = $('XLSX Prepare LLM Prompt').first().json.sheetName;\n\n// Get LLM description (OpenAI node outputs message.content)\nconst llmResponse = $json.message?.content || $json.content || 'Tabular dataset';\nconst description = llmResponse.trim();\n\n// Build compact column list\nconst columnList = columnNames.map(col => {\n const colInfo = metadata.columns[col];\n return colInfo.all_numeric ? `${col} (num)` : col;\n}).join(', ');\n\n// Build content WITH description\nconst content = `${description}\\n\\nDataset: ${fileTitle}\\nSheet: ${sheetName}\\nType: Spreadsheet\\nRows: ${metadata.row_count}\\nColumns: ${columnList}`;\n\nreturn {\n json: {\n content,\n description,\n sheet_id: sheetRow.id,\n record_manager_id: $('Set Hash Record Id').first().json.hash_record_id,\n sheet_name: sheetName,\n metadata: {\n type: 'tabular',\n file_id: fileId,\n sheet_id: sheetRow.id,\n sheet_name: sheetName,\n row_count: metadata.row_count,\n columns: columnNames,\n description: description\n }\n }\n};"
},
"executeOnce": true,
"typeVersion": 2
},
{
"id": "c722b422-4c0c-416a-a0f9-86906ab84a07",
"name": "XLSX Generate Pointer Embedding",
"type": "n8n-nodes-base.httpRequest",
"position": [
3168,
1888
],
"parameters": {
"url": "https://api.openai.com/v1/embeddings",
"method": "POST",
"options": {},
"jsonBody": "={\n \"input\": {{ JSON.stringify($json.content) }},\n \"model\": \"text-embedding-3-small\"\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "openAiApi"
},
"typeVersion": 4.2
},
{
"id": "aa4c8cfb-ee92-470d-bb22-d2ac85ff12ad",
"name": "XLSX Insert Pointer to Documents Hybrid",
"type": "n8n-nodes-base.supabase",
"position": [
3392,
1968
],
"parameters": {
"schema": "={{ $('Configure Settings').first().json.schema }}",
"tableId": "documents_hybrid",
"fieldsUi": {
"fieldValues": [
{
"fieldId": "content",
"fieldValue": "={{ $('XLSX Build Pointer Content').item.json.content }}"
},
{
"fieldId": "embedding",
"fieldValue": "={{ JSON.stringify($json.data[0].embedding) }}"
},
{
"fieldId": "metadata",
"fieldValue": "={{ $('XLSX Build Pointer Content').item.json.metadata }}"
},
{
"fieldId": "record_manager_id",
"fieldValue": "={{ $('XLSX Build Pointer Content').item.json.record_manager_id }}"
},
{
"fieldId": "sheet_id",
"fieldValue": "={{ $('XLSX Build Pointer Content').item.json.sheet_id }}"
}
]
},
"useCustomSchema": true
},
"typeVersion": 1
},
{
"id": "8b6c4771-fbbd-45a1-9adf-d2744b1b37a6",
"name": "RAG Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
-2608,
2784
],
"parameters": {
"options": {
"systemMessage": "=Placeholder"
}
},
"typeVersion": 3
},
{
"id": "e4d646d9-abd9-4123-8f06-de8b3321cdaf",
"name": "GPT-4o",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
-2784,
3008
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4o",
"cachedResultName": "gpt-4o"
},
"options": {
"temperature": 0
},
"builtInTools": {
"webSearch": {
"searchContextSize": "low"
}
}
},
"typeVersion": 1.3
},
{
"id": "f5d9d03d-0e96-4059-8c71-d474744de7a8",
"name": "Postgres Chat Memory",
"type": "@n8n/n8n-nodes-langchain.memoryPostgresChat",
"position": [
-2656,
3008
],
"parameters": {
"tableName": "={{ $('Parse & Extract Data').item.json.supabase_schema }}.chat_histories",
"contextWindowLength": 10
},
"typeVersion": 1.3
},
{
"id": "3963a0d4-62cb-4923-83ab-71b3dc50d6e2",
"name": "Tool: Search Knowledge Base",
"type": "@n8n/n8n-nodes-langchain.toolWorkflow",
"position": [
-2528,
3008
],
"parameters": {
"workflowId": {
"__rl": true,
"mode": "list",
"value": "540VwCSiEmDTAAk0",
"cachedResultUrl": "/workflow/540VwCSiEmDTAAk0",
"cachedResultName": "RAG Chatbot Template"
},
"description": "=Search the knowledge base for ANY information - documents, PDFs, and tabular data (CSV, Excel, Google Sheets).\n\nThis is your PRIMARY search tool. Always start here.\n\nFor tabular data results, the response will include:\n- A description of what the dataset contains\n- metadata.type = 'tabular' (indicates this is tabular data)\n- metadata.sheet_id (UUID to use with 'Tool: Query Tabular Data')\n- metadata.columns (list of column names)\n- metadata.row_count (number of rows)\n\nWorkflow for tabular data:\n1. Search here first to find relevant datasets\n2. If you need exact column formats/sample values, use 'Tool: Get Sheet Details'\n3. Use 'Tool: Query Tabular Data' with the sheet_id to run SQL queries",
"workflowInputs": {
"value": {
"query": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('query', `The search query to find relevant information`, 'string') }}"
},
"schema": [
{
"id": "query",
"type": "string",
"display": true,
"required": false,
"displayName": "query",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"query"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
}
},
"typeVersion": 2.2
},
{
"id": "f75eadb6-0398-4847-bf02-267277d41fb8",
"name": "Tool: Get Sheet Details",
"type": "n8n-nodes-base.postgresTool",
"position": [
-2400,
3008
],
"parameters": {
"limit": 1,
"table": {
"__rl": true,
"mode": "list",
"value": "tabular_document_sheets",
"cachedResultName": "tabular_document_sheets"
},
"where": {
"values": [
{
"value": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('sheet_id', `The sheet UUID from search results (metadata.sheet_id)`, 'string') }}",
"column": "id"
}
]
},
"schema": {
"__rl": true,
"mode": "name",
"value": "={{ $('Parse & Extract Data').item.json.supabase_schema }}"
},
"options": {
"outputColumns": [
"id",
"sheet_name",
"schema",
"metadata"
]
},
"operation": "select",
"descriptionType": "manual",
"toolDescription": "=Get detailed metadata for a specific sheet including sample values and column statistics. Use this AFTER 'Tool: Search Knowledge Base' when you need to understand exact data formats before constructing a SQL query.\n\nInput: sheet_id (UUID string from search results metadata.sheet_id)\n\nReturns:\n- id: The sheet UUID (use this in SQL queries)\n- sheet_name: Name of the sheet/tab\n- schema: Array of column names\n- metadata.columns: Detailed info per column including:\n - sample_values: Example values from the data\n - all_numeric: Whether column contains only numbers\n - unique_count: Number of distinct values\n - null_count: Number of empty values\n\nUse this to understand exact value formats (e.g., 'Sales' vs 'SALES' vs 'sales-dept') before writing SQL."
},
"typeVersion": 2.6
},
{
"id": "7c08e765-b9ab-4dbf-b738-d001b060577a",
"name": "Tool: Query Tabular Data",
"type": "n8n-nodes-base.postgresTool",
"position": [
-2272,
3008
],
"parameters": {
"query": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('sql_query', `The SQL query to execute. Always include WHERE sheet_id = 'uuid' clause.`, 'string') }}",
"options": {},
"operation": "executeQuery",
"descriptionType": "manual",
"toolDescription": "=Execute a SQL query on tabular data stored in the database.\n\nIMPORTANT: Always use the fully qualified table name: {{ $('Parse & Extract Data').item.json.supabase_schema }}.tabular_document_rows\n\nTable Structure:\n- sheet_id (UUID): Links to a specific sheet - ALWAYS filter by this\n- record_manager_id (UUID): Links to the parent file (use to query across all sheets in a file)\n- row_data (JSONB): Contains the actual data with keys matching column names\n\nQuerying JSONB Data:\n- Use ->> operator to extract text values: row_data->>'column_name'\n- Cast numeric values: (row_data->>'amount')::numeric\n- Cast dates: (row_data->>'date')::date\n\nExample Queries:\n\n-- Sum a numeric column for a specific sheet\nSELECT SUM((row_data->>'revenue')::numeric) AS total_revenue\nFROM {{ $('Parse & Extract Data').item.json.supabase_schema }}.tabular_document_rows\nWHERE sheet_id = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890';\n\n-- Group by a text column\nSELECT row_data->>'department' AS department,\n COUNT(*) AS employee_count,\n AVG((row_data->>'salary')::numeric) AS avg_salary\nFROM {{ $('Parse & Extract Data').item.json.supabase_schema }}.tabular_document_rows\nWHERE sheet_id = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'\nGROUP BY row_data->>'department';\n\n-- Filter with conditions\nSELECT row_data->>'name' AS name,\n (row_data->>'sales')::numeric AS sales\nFROM {{ $('Parse & Extract Data').item.json.supabase_schema }}.tabular_document_rows\nWHERE sheet_id = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'\n AND (row_data->>'sales')::numeric > 10000\nORDER BY (row_data->>'sales')::numeric DESC\nLIMIT 10;\n\n-- Query across all sheets in a file\nSELECT SUM((row_data->>'amount')::numeric) AS total\nFROM {{ $('Parse & Extract Data').item.json.supabase_schema }}.tabular_document_rows\nWHERE record_manager_id = 'file-uuid-here';"
},
"typeVersion": 2.6
},
{
"id": "ad40445c-3a6d-4292-b2a4-2038c869a699",
"name": "Sticky: Drive Sync",
"type": "n8n-nodes-base.stickyNote",
"position": [
-5088,
432
],
"parameters": {
"width": 2464,
"height": 588,
"content": "## Google Drive Sync\nMonitors Google Drive folder, compares files with database records, handles file deletions and updates"
},
"typeVersion": 1
},
{
"id": "65eeff6b-f7bc-499c-b16d-ee6cc4aaae17",
"name": "Sticky: Triggers",
"type": "n8n-nodes-base.stickyNote",
"position": [
-4160,
1696
],
"parameters": {
"color": 2,
"width": 636,
"height": 560,
"content": "## Triggers & Entry Points\nManual trigger, chat webhook, Google Drive events, Firecrawl webhook - all workflow entry points"
},
"typeVersion": 1
},
{
"id": "af4795dd-8824-479c-91de-1c90708edd36",
"name": "Sticky: File Processing",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3504,
1040
],
"parameters": {
"color": 3,
"width": 4016,
"height": 1224,
"content": "## File Processing Pipeline\nDownloads files, generates SHA256 hashes, checks for duplicates, routes by MIME type, manages record lifecycle"
},
"typeVersion": 1
},
{
"id": "9abecbc9-a9b1-499b-becd-5d0b116431e6",
"name": "Sticky: Document Extraction",
"type": "n8n-nodes-base.stickyNote",
"position": [
528,
192
],
"parameters": {
"color": 4,
"width": 4048,
"height": 1028,
"content": "## Document Extraction & OCR\nRoutes by file type, processes PDFs with Mistral OCR, extracts images, handles PDF/DOCX/DOC/Google Docs/RTF/ODT/PPTX/PPT/TXT/MD files"
},
"typeVersion": 1
},
{
"id": "95242f28-8938-48e6-b529-2244afb42437",
"name": "Sticky: Chunking",
"type": "n8n-nodes-base.stickyNote",
"position": [
4608,
416
],
"parameters": {
"color": 5,
"width": 1456,
"height": 700,
"content": "## Chunking & Vector Embedding\nSplits documents into chunks, generates contextual descriptions, creates embeddings, stores in Supabase vector store"
},
"typeVersion": 1
},
{
"id": "b7fb8420-2e99-4462-87a2-1969ca2860f6",
"name": "Sticky: RAG Search",
"type": "n8n-nodes-base.stickyNote",
"position": [
-5136,
3840
],
"parameters": {
"color": 6,
"width": 2100,
"height": 700,
"content": "## RAG Search (Subworkflow)\nGenerates query embeddings, executes hybrid search (vector + FTS), reranks results with Cohere"
},
"typeVersion": 1
},
{
"id": "56a935c4-4bb1-419d-9d8c-6b33d258b70c",
"name": "Sticky: Chat Interface",
"type": "n8n-nodes-base.stickyNote",
"position": [
-5136,
2720
],
"parameters": {
"width": 2228,
"height": 1100,
"content": "## Chat Message Processing\nParses incoming chat messages, handles file uploads, analyzes images, prepares input for AI agent"
},
"typeVersion": 1
},
{
"id": "0cd57ccb-2097-44ec-a780-5eebff169513",
"name": "Sticky: AI Agent",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2880,
2688
],
"parameters": {
"color": 7,
"width": 900,
"height": 500,
"content": "## AI Agent (hellenicAI)\nGPT-4o powered agent with memory, knowledge base search, and tabular data query tools"
},
"typeVersion": 1
},
{
"id": "af62dab6-23be-44eb-8ed7-fcc56a87e199",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2096,
3232
],
"parameters": {
"color": 4,
"width": 384,
"height": 192,
"content": "## Send Response To Omnichat\n"
},
"typeVersion": 1
},
{
"id": "3de0c5e2-d03f-4865-bea8-a07b6e0e51fd",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-4176,
2304
],
"parameters": {
"color": 6,
"width": 640,
"height": 272,
"content": "## Start Firecrawl crawl. \nMake sure to change the website in the \"Set URL to Crawl\" node\n"
},
"typeVersion": 1
},
{
"id": "e71a55f0-62b2-45d7-90cc-1dc94404af5c",
"name": "Sticky: CSV Pipeline",
"type": "n8n-nodes-base.stickyNote",
"position": [
1680,
1248
],
"parameters": {
"color": 6,
"width": 3120,
"height": 376,
"content": "## CSV Ingestion Pipeline\nExtracts CSV data, analyzes column metadata, stores rows, generates LLM descriptions, creates searchable vector pointers"
},
"typeVersion": 1
},
{
"id": "df8affd8-3e27-4411-b4bc-9764990fdbbc",
"name": "Sticky: XLSX Pipeline",
"type": "n8n-nodes-base.stickyNote",
"position": [
544,
1680
],
"parameters": {
"color": 5,
"width": 3024,
"height": 584,
"content": "## XLSX/XLS/Google Sheets Pipeline\nExtracts multi-sheet workbooks, analyzes column metadata per sheet, stores rows, generates LLM descriptions, creates searchable vector pointers"
},
"typeVersion": 1
},
{
"id": "a660c6f5-f26f-4bf1-8916-507aef9be93f",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3632,
3232
],
"parameters": {
"color": 3,
"width": 336,
"height": 272,
"content": "## COMMUNITY NODE!!!\nMake sure it's installed properly after every n8n update"
},
"typeVersion": 1
}
],
"pinData": {},
"connections": {
"GPT-4o": {
"ai_languageModel": [
[
{
"node": "RAG Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Is File?": {
"main": [
[
{
"node": "Process Chat File Upload",
"type": "main",
"index": 0
}
],
[
{
"node": "Prepare Agent Input",
"type": "main",
"index": 0
}
]
]
},
"Is Image?": {
"main": [
[
{
"node": "Analyze Image",
"type": "main",
"index": 0
}
],
[
{
"node": "Set 'File Not Supported' Message",
"type": "main",
"index": 0
}
]
]
},
"RAG Agent": {
"main": [
[
{
"node": "Send Response",
"type": "main",
"index": 0
}
]
]
},
"Chat Message": {
"main": [
[
{
"node": "Parse & Extract Data",
"type": "main",
"index": 0
}
]
]
},
"Convert File": {
"main": [
[
{
"node": "Format Files for Chat Input",
"type": "main",
"index": 0
}
]
]
},
"Analyze Image": {
"main": [
[
{
"node": "Prepare Agent Input",
"type": "main",
"index": 0
}
]
]
},
"Extract Pages": {
"main": [
[
{
"node": "Images Exist?",
"type": "main",
"index": 0
}
]
]
},
"Filter Events": {
"main": [
[
{
"node": "Is File?",
"type": "main",
"index": 0
}
]
]
},
"Images Exist?": {
"main": [
[
{
"node": "Extract Images from Pages",
"type": "main",
"index": 0
}
],
[
{
"node": "Merge OCR with Uploads",
"type": "main",
"index": 0
}
]
]
},
"Add Sheet Row1": {
"main": [
[
{
"node": "Wait for Schema Update1",
"type": "main",
"index": 0
}
]
]
},
"Extract Sheets": {
"main": [
[
{
"node": "Loops Over Sheets1",
"type": "main",
"index": 0
}
]
]
},
"Results Found?": {
"main": [
[
{
"node": "Extract Search Results",
"type": "main",
"index": 0
}
],
[
{
"node": "Return \"No results found!\" Message",
"type": "main",
"index": 0
}
]
]
},
"Check File Type": {
"main": [
[
{
"node": "Is Image?",
"type": "main",
"index": 0
}
]
]
},
"Check MIME Type": {
"main": [
[
{
"node": "Set Data Type Unstructured",
"type": "main",
"index": 0
}
],
[
{
"node": "Set Data Type Tabular",
"type": "main",
"index": 0
}
]
]
},
"On File Updated": {
"main": [
[
{
"node": "Batch Process Files",
"type": "main",
"index": 0
}
]
]
},
"Set Sync Config": {
"main": [
[
{
"node": "Get All Record Manager Rows",
"type": "main",
"index": 0
},
{
"node": "List Files in Google Drive",
"type": "main",
"index": 0
}
]
]
},
"Extract CSV Data": {
"main": [
[
{
"node": "Aggregate CSV Rows",
"type": "main",
"index": 0
}
]
]
},
"Rate Limit Delay": {
"main": [
[
{
"node": "Batch Process Chunks",
"type": "main",
"index": 0
}
]
]
},
"Set URL to Crawl": {
"main": [
[
{
"node": "Start Firecrawl Crawl",
"type": "main",
"index": 0
}
]
]
},
"Split Data Rows1": {
"main": [
[
{
"node": "Insert Tabular Row1",
"type": "main",
"index": 0
}
]
]
},
"Add CSV Sheet Row": {
"main": [
[
{
"node": "Wait for CSV Schema Update",
"type": "main",
"index": 0
}
]
]
},
"Set Combined Text": {
"main": [
[
{
"node": "Split Document into Chunks",
"type": "main",
"index": 0
}
]
]
},
"Split Drive Files": {
"main": [
[
{
"node": "Compare Drive vs Database",
"type": "main",
"index": 1
}
]
]
},
"Aggregate CSV Rows": {
"main": [
[
{
"node": "Analyze CSV Column Metadata",
"type": "main",
"index": 0
}
]
]
},
"Configure Settings": {
"main": [
[
{
"node": "Is Webhook Source?",
"type": "main",
"index": 0
}
]
]
},
"Generate Embedding": {
"main": [
[
{
"node": "Insert into Supabase",
"type": "main",
"index": 0
}
]
]
},
"Handle OCR Failure": {
"main": [
[
{
"node": "Batch Process Files",
"type": "main",
"index": 0
}
]
]
},
"Insert Hash Record": {
"main": [
[
{
"node": "Set Hash Record Id",
"type": "main",
"index": 0
}
]
]
},
"Is Webhook Source?": {
"main": [
[
{
"node": "Has Markdown Content?",
"type": "main",
"index": 0
}
],
[
{
"node": "Download File for Hash",
"type": "main",
"index": 0
}
]
]
},
"Loops Over Sheets1": {
"main": [
[
{
"node": "Processing Complete",
"type": "main",
"index": 0
}
],
[
{
"node": "Analyze Sheet Column Metadata1",
"type": "main",
"index": 0
}
]
]
},
"Route by File Type": {
"main": [
[
{
"node": "Upload File to Mistral",
"type": "main",
"index": 0
}
],
[
{
"node": "Upload File to Mistral",
"type": "main",
"index": 0
}
],
[
{
"node": "Upload File to Mistral",
"type": "main",
"index": 0
}
],
[
{
"node": "Upload File to Mistral",
"type": "main",
"index": 0
}
],
[
{
"node": "Upload File to Mistral",
"type": "main",
"index": 0
}
],
[
{
"node": "Upload File to Mistral",
"type": "main",
"index": 0
}
],
[
{
"node": "Upload File to Mistral",
"type": "main",
"index": 0
}
],
[
{
"node": "Upload File to Mistral",
"type": "main",
"index": 0
}
],
[
{
"node": "Extract Text from Plain Files",
"type": "main",
"index": 0
}
],
[
{
"node": "Extract Text from Plain Files",
"type": "main",
"index": 0
}
],
[
{
"node": "Extract CSV Data",
"type": "main",
"index": 0
}
],
[
{
"node": "Extract Sheets",
"type": "main",
"index": 0
}
],
[
{
"node": "Extract Sheets",
"type": "main",
"index": 0
}
],
[
{
"node": "Extract Sheets",
"type": "main",
"index": 0
}
]
]
},
"Set Hash Record Id": {
"main": [
[
{
"node": "Is Webhook Source? (Post-Hash)",
"type": "main",
"index": 0
}
]
]
},
"Batch Process Files": {
"main": [
[],
[
{
"node": "Configure Settings",
"type": "main",
"index": 0
}
]
]
},
"Insert Tabular Row1": {
"main": [
[
{
"node": "XLSX Prepare LLM Prompt",
"type": "main",
"index": 0
}
]
]
},
"Prepare Agent Input": {
"main": [
[
{
"node": "RAG Agent",
"type": "main",
"index": 0
}
]
]
},
"Processing Complete": {
"main": [
[
{
"node": "Batch Process Files",
"type": "main",
"index": 0
}
]
]
},
"Split CSV Data Rows": {
"main": [
[
{
"node": "Insert CSV Tabular Row",
"type": "main",
"index": 0
}
]
]
},
"Batch Process Chunks": {
"main": [
[
{
"node": "Processing Complete",
"type": "main",
"index": 0
}
],
[
{
"node": "Generate Chunk Context",
"type": "main",
"index": 0
}
]
]
},
"Concatenate CSV Data": {
"main": [
[
{
"node": "Wait for CSV Schema Update",
"type": "main",
"index": 1
}
]
]
},
"Filter Trashed Files": {
"main": [
[
{
"node": "Batch Process Files",
"type": "main",
"index": 0
}
]
]
},
"Generate SHA256 Hash": {
"main": [
[
{
"node": "Lookup Existing Record",
"type": "main",
"index": 0
}
]
]
},
"Get Mistral File URL": {
"main": [
[
{
"node": "Process with Mistral OCR",
"type": "main",
"index": 0
}
],
[
{
"node": "Handle OCR Failure",
"type": "main",
"index": 0
}
]
]
},
"Insert into Supabase": {
"main": [
[
{
"node": "Rate Limit Delay",
"type": "main",
"index": 0
}
]
]
},
"Parse & Extract Data": {
"main": [
[
{
"node": "Filter Events",
"type": "main",
"index": 0
}
]
]
},
"Postgres Chat Memory": {
"ai_memory": [
[
{
"node": "RAG Agent",
"type": "ai_memory",
"index": 0
}
]
]
},
"Route by Hash Status": {
"main": [
[
{
"node": "Check MIME Type",
"type": "main",
"index": 0
}
],
[
{
"node": "Delete Existing Vectors",
"type": "main",
"index": 0
}
]
]
},
"Execute Hybrid Search": {
"main": [
[
{
"node": "Results Found?",
"type": "main",
"index": 0
}
],
[
{
"node": "Return Error Message",
"type": "main",
"index": 0
}
]
]
},
"Has Markdown Content?": {
"main": [
[
{
"node": "Encode Markdown to Base64",
"type": "main",
"index": 0
}
],
[
{
"node": "Batch Process Files",
"type": "main",
"index": 0
}
]
]
},
"Merge Upload Response": {
"main": [
[
{
"node": "Collect Uploaded Images",
"type": "main",
"index": 0
}
]
]
},
"Set Data Type Tabular": {
"main": [
[
{
"node": "Insert Hash Record",
"type": "main",
"index": 0
}
]
]
},
"Set Supabase Settings": {
"main": [
[
{
"node": "Generate Query Embedding",
"type": "main",
"index": 0
}
]
]
},
"CSV Prepare LLM Prompt": {
"main": [
[
{
"node": "CSV Generate Description",
"type": "main",
"index": 0
}
]
]
},
"Collect Search Results": {
"main": [
[
{
"node": "Rerank Results with Cohere",
"type": "main",
"index": 0
}
]
]
},
"Combine Markdown Pages": {
"main": [
[
{
"node": "Set Combined Text",
"type": "main",
"index": 0
}
]
]
},
"Download File for Hash": {
"main": [
[
{
"node": "Generate SHA256 Hash",
"type": "main",
"index": 0
}
]
]
},
"Extract Search Results": {
"main": [
[
{
"node": "Collect Search Results",
"type": "main",
"index": 0
}
]
]
},
"Generate Chunk Context": {
"main": [
[
{
"node": "Merge Context with Chunk",
"type": "main",
"index": 0
}
]
]
},
"Insert CSV Tabular Row": {
"main": [
[
{
"node": "CSV Prepare LLM Prompt",
"type": "main",
"index": 0
}
]
]
},
"Lookup Existing Record": {
"main": [
[
{
"node": "Route by Hash Status",
"type": "main",
"index": 0
}
]
]
},
"Merge OCR with Uploads": {
"main": [
[
{
"node": "Split Pages for Processing",
"type": "main",
"index": 0
}
]
]
},
"Prepare Image Metadata": {
"main": [
[
{
"node": "Merge Upload Response",
"type": "main",
"index": 1
},
{
"node": "Convert Base64 to Binary",
"type": "main",
"index": 0
}
]
]
},
"Set File ID from Drive": {
"main": [
[
{
"node": "Loop Over Deleted Files",
"type": "main",
"index": 0
}
]
]
},
"Upload File to Mistral": {
"main": [
[
{
"node": "Get Mistral File URL",
"type": "main",
"index": 0
}
],
[
{
"node": "Handle OCR Failure",
"type": "main",
"index": 0
}
]
]
},
"Collect Uploaded Images": {
"main": [
[
{
"node": "Merge OCR with Uploads",
"type": "main",
"index": 0
}
]
]
},
"Delete Existing Vectors": {
"main": [
[
{
"node": "Delete Images from Storage (Update)",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Deleted Files": {
"main": [
[],
[
{
"node": "Delete File Vectors from Documents",
"type": "main",
"index": 0
}
]
]
},
"Tool: Get Sheet Details": {
"ai_tool": [
[
{
"node": "RAG Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Upload Image to Storage": {
"main": [
[
{
"node": "Extract Uploaded Filename",
"type": "main",
"index": 0
}
]
]
},
"Wait for Schema Update1": {
"main": [
[
{
"node": "Set Text for Tabular Data1",
"type": "main",
"index": 0
}
]
]
},
"XLSX Prepare LLM Prompt": {
"main": [
[
{
"node": "XLSX Generate Description",
"type": "main",
"index": 0
}
]
]
},
"CSV Generate Description": {
"main": [
[
{
"node": "CSV Build Pointer Content",
"type": "main",
"index": 0
}
]
]
},
"Convert Base64 to Binary": {
"main": [
[
{
"node": "Upload Image to Storage",
"type": "main",
"index": 0
}
]
]
},
"Execute Workflow Trigger": {
"main": [
[
{
"node": "Set Supabase Settings",
"type": "main",
"index": 0
}
]
]
},
"Filter Non-Trashed Files": {
"main": [
[
{
"node": "Set File ID from Drive",
"type": "main",
"index": 0
}
]
]
},
"Generate Query Embedding": {
"main": [
[
{
"node": "Execute Hybrid Search",
"type": "main",
"index": 0
}
],
[
{
"node": "Return Error Message",
"type": "main",
"index": 0
}
]
]
},
"Merge Context with Chunk": {
"main": [
[
{
"node": "Generate Embedding",
"type": "main",
"index": 0
}
]
]
},
"Process Chat File Upload": {
"main": [
[
{
"node": "Route Chat Upload by Type",
"type": "main",
"index": 0
}
]
]
},
"Process with Mistral OCR": {
"main": [
[
{
"node": "Merge OCR with Uploads",
"type": "main",
"index": 1
},
{
"node": "Extract Pages",
"type": "main",
"index": 0
}
],
[
{
"node": "Handle OCR Failure",
"type": "main",
"index": 0
}
]
]
},
"Receive Firecrawl Events": {
"main": [
[
{
"node": "Batch Process Files",
"type": "main",
"index": 0
}
]
]
},
"Tool: Query Tabular Data": {
"ai_tool": [
[
{
"node": "RAG Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"CSV Build Pointer Content": {
"main": [
[
{
"node": "CSV Generate Pointer Embedding",
"type": "main",
"index": 0
}
]
]
},
"Compare Drive vs Database": {
"main": [
[
{
"node": "Filter Google Drive Files",
"type": "main",
"index": 0
}
],
[],
[
{
"node": "Filter Non-Trashed Files",
"type": "main",
"index": 0
}
],
[
{
"node": "Filter Trashed Files",
"type": "main",
"index": 0
}
]
]
},
"Concatenate Tabular Data1": {
"main": [
[
{
"node": "Wait for Schema Update1",
"type": "main",
"index": 1
}
]
]
},
"Encode Markdown to Base64": {
"main": [
[
{
"node": "Convert Markdown to Binary",
"type": "main",
"index": 0
}
]
]
},
"Extract Images from Pages": {
"main": [
[
{
"node": "Prepare Image Metadata",
"type": "main",
"index": 0
}
]
]
},
"Extract Uploaded Filename": {
"main": [
[
{
"node": "Merge Upload Response",
"type": "main",
"index": 0
}
]
]
},
"Filter Google Drive Files": {
"main": [
[
{
"node": "Set File ID from Database",
"type": "main",
"index": 0
}
]
]
},
"Route Chat Upload by Type": {
"main": [
[
{
"node": "Extract PDF Content (Chat)",
"type": "main",
"index": 0
}
],
[
{
"node": "Convert File",
"type": "main",
"index": 0
}
],
[
{
"node": "Convert File",
"type": "main",
"index": 0
}
],
[
{
"node": "Set File Unsupported Response",
"type": "main",
"index": 0
}
],
[
{
"node": "Convert File",
"type": "main",
"index": 0
}
],
[
{
"node": "Convert File",
"type": "main",
"index": 0
}
],
[
{
"node": "Convert File",
"type": "main",
"index": 0
}
],
[
{
"node": "Convert File",
"type": "main",
"index": 0
}
],
[
{
"node": "Convert File",
"type": "main",
"index": 0
}
],
[
{
"node": "Convert File",
"type": "main",
"index": 0
}
],
[
{
"node": "Convert File",
"type": "main",
"index": 0
}
],
[
{
"node": "Convert File",
"type": "main",
"index": 0
}
],
[
{
"node": "Convert File",
"type": "main",
"index": 0
}
],
[
{
"node": "Check File Type",
"type": "main",
"index": 0
}
]
]
},
"Set File ID from Database": {
"main": [
[
{
"node": "Loop Over Deleted Files",
"type": "main",
"index": 0
}
]
]
},
"XLSX Generate Description": {
"main": [
[
{
"node": "XLSX Build Pointer Content",
"type": "main",
"index": 0
}
]
]
},
"Convert Markdown to Binary": {
"main": [
[
{
"node": "Generate SHA256 Hash",
"type": "main",
"index": 0
}
]
]
},
"Extract PDF Content (Chat)": {
"main": [
[
{
"node": "Prepare Agent Input",
"type": "main",
"index": 0
}
]
]
},
"List Files in Google Drive": {
"main": [
[
{
"node": "Split Drive Files",
"type": "main",
"index": 0
}
]
]
},
"Rerank Results with Cohere": {
"main": [
[
{
"node": "Format Reranked Output",
"type": "main",
"index": 0
}
],
[
{
"node": "Return Error Message",
"type": "main",
"index": 0
}
]
]
},
"Set CSV Text for Embedding": {
"main": [
[
{
"node": "Split CSV Data Rows",
"type": "main",
"index": 0
}
]
]
},
"Set Data Type Unstructured": {
"main": [
[
{
"node": "Insert Hash Record",
"type": "main",
"index": 0
}
]
]
},
"Set Text for Tabular Data1": {
"main": [
[
{
"node": "Split Data Rows1",
"type": "main",
"index": 0
}
]
]
},
"Split Document into Chunks": {
"main": [
[
{
"node": "Batch Process Chunks",
"type": "main",
"index": 0
}
]
]
},
"Split Pages for Processing": {
"main": [
[
{
"node": "Combine Markdown Pages",
"type": "main",
"index": 0
}
]
]
},
"Wait for CSV Schema Update": {
"main": [
[
{
"node": "Set CSV Text for Embedding",
"type": "main",
"index": 0
}
]
]
},
"XLSX Build Pointer Content": {
"main": [
[
{
"node": "XLSX Generate Pointer Embedding",
"type": "main",
"index": 0
}
]
]
},
"Analyze CSV Column Metadata": {
"main": [
[
{
"node": "Add CSV Sheet Row",
"type": "main",
"index": 0
},
{
"node": "Concatenate CSV Data",
"type": "main",
"index": 0
}
]
]
},
"Format Files for Chat Input": {
"main": [
[
{
"node": "Prepare Agent Input",
"type": "main",
"index": 0
}
]
]
},
"Get All Record Manager Rows": {
"main": [
[
{
"node": "Compare Drive vs Database",
"type": "main",
"index": 0
}
]
]
},
"Tool: Search Knowledge Base": {
"ai_tool": [
[
{
"node": "RAG Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Delete Record on File Update": {
"main": [
[
{
"node": "Check MIME Type",
"type": "main",
"index": 0
}
]
]
},
"Download File for Processing": {
"main": [
[
{
"node": "Route by File Type",
"type": "main",
"index": 0
}
]
]
},
"Extract Text from Plain Files": {
"main": [
[
{
"node": "Set Combined Text",
"type": "main",
"index": 0
}
]
]
},
"Set File Unsupported Response": {
"main": [
[
{
"node": "Send Response",
"type": "main",
"index": 0
}
]
]
},
"Analyze Sheet Column Metadata1": {
"main": [
[
{
"node": "Add Sheet Row1",
"type": "main",
"index": 0
},
{
"node": "Concatenate Tabular Data1",
"type": "main",
"index": 0
}
]
]
},
"CSV Generate Pointer Embedding": {
"main": [
[
{
"node": "CSV Insert Pointer to Documents Hybrid",
"type": "main",
"index": 0
}
]
]
},
"Is Webhook Source? (Post-Hash)": {
"main": [
[
{
"node": "Encode Webhook Markdown to Base64",
"type": "main",
"index": 0
}
],
[
{
"node": "Download File for Processing",
"type": "main",
"index": 0
}
]
]
},
"Delete File From Record Manager": {
"main": [
[
{
"node": "Delete Images from Storage (Deletion)",
"type": "main",
"index": 0
}
]
]
},
"XLSX Generate Pointer Embedding": {
"main": [
[
{
"node": "XLSX Insert Pointer to Documents Hybrid",
"type": "main",
"index": 0
}
]
]
},
"Schedule File Sync (Every 15Min)": {
"main": [
[
{
"node": "Set Sync Config",
"type": "main",
"index": 0
}
]
]
},
"Set 'File Not Supported' Message": {
"main": [
[
{
"node": "Send Response",
"type": "main",
"index": 0
}
]
]
},
"Encode Webhook Markdown to Base64": {
"main": [
[
{
"node": "Convert Webhook Markdown to Binary",
"type": "main",
"index": 0
}
]
]
},
"Convert Webhook Markdown to Binary": {
"main": [
[
{
"node": "Extract Text from Plain Files",
"type": "main",
"index": 0
}
]
]
},
"Delete File Vectors from Documents": {
"main": [
[
{
"node": "Delete File From Record Manager",
"type": "main",
"index": 0
}
]
]
},
"Delete Images from Storage (Update)": {
"main": [
[
{
"node": "Delete Record on File Update",
"type": "main",
"index": 0
}
]
]
},
"When clicking ‘Execute workflow’": {
"main": [
[
{
"node": "Set URL to Crawl",
"type": "main",
"index": 0
}
]
]
},
"Delete Images from Storage (Deletion)": {
"main": [
[
{
"node": "Loop Over Deleted Files",
"type": "main",
"index": 0
}
]
]
},
"CSV Insert Pointer to Documents Hybrid": {
"main": [
[
{
"node": "Processing Complete",
"type": "main",
"index": 0
}
]
]
},
"XLSX Insert Pointer to Documents Hybrid": {
"main": [
[
{
"node": "Loops Over Sheets1",
"type": "main",
"index": 0
}
]
]
}
}
}