AutomationFlowsAI & RAG › Exact Recall Across Collections

Exact Recall Across Collections

Exact-Recall-Across-Collections. Uses supabase, postgres, documentDefaultDataLoader, textSplitterCharacterTextSplitter. Event-driven trigger; 49 nodes.

Event trigger★★★★★ complexityAI-powered49 nodesSupabasePostgresDocument Default Data LoaderText Splitter Character Text SplitterSupabase Vector StoreGoogle Gemini EmbeddingsEvaluation TriggerGoogle Drive
AI & RAG Trigger: Event Nodes: 49 Complexity: ★★★★★ AI nodes: yes Added:

This workflow follows the Chainllm → Documentdefaultdataloader recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "nodes": [
    {
      "parameters": {
        "content": "## RAG Agent class 6",
        "height": 421,
        "width": 767
      },
      "id": "ba5902f9-6b35-4d89-a217-192920c2fc47",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -592,
        240
      ]
    },
    {
      "parameters": {
        "content": "# Add a Google Drive File to Vector DB",
        "height": 847,
        "width": 2213,
        "color": 5
      },
      "id": "da9f83e7-a8e5-4b57-b0a7-e612f1aefc36",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -784,
        832
      ]
    },
    {
      "parameters": {
        "operation": "delete",
        "tableId": "documents",
        "filterType": "string",
        "filterString": "=metadata->>file_id=like.*{{ $('Set File ID2').item.json.file_id }}*"
      },
      "id": "3aad30ea-628b-465f-87ef-f8b8e6d6011c",
      "name": "Delete Old Doc Rows",
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        1360,
        848
      ],
      "alwaysOutputData": true,
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "disabled": true
    },
    {
      "parameters": {
        "content": "## Run Each Node Once to Set Up Database Tables",
        "height": 260,
        "width": 680,
        "color": 3
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -768,
        944
      ],
      "typeVersion": 1,
      "id": "ef9f43c8-eab3-4dce-a20e-b913377ddbd1",
      "name": "Sticky Note3"
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "CREATE TABLE document_metadata (\n    id TEXT PRIMARY KEY,\n    title TEXT,\n    url TEXT,\n    created_at TIMESTAMP DEFAULT NOW(),\n    schema TEXT\n);",
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        -496,
        1008
      ],
      "id": "73905f10-c184-4cb9-9e71-6fe77521b0e7",
      "name": "Create Document Metadata Table",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "CREATE TABLE document_rows (\n    id SERIAL PRIMARY KEY,\n    dataset_id TEXT REFERENCES document_metadata(id),\n    row_data JSONB  -- Store the actual row data\n);",
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        -288,
        1008
      ],
      "id": "05f1476a-0713-497d-b703-db757e88a271",
      "name": "Create Document Rows Table (for Tabular Data)",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "-- Check if pgvector extension exists, create only if it doesn't\nCREATE EXTENSION IF NOT EXISTS vector;\n\n-- Create a table to store your documents\n-- DROP TABLE IF EXISTS documents;\nCREATE TABLE documents (\n  id bigserial PRIMARY KEY,\n  content text, -- corresponds to Document.pageContent\n  metadata jsonb, -- corresponds to Document.metadata\n  embedding vector(768) -- 1536 works for OpenAI embeddings, change if needed\n);\n\n-- -- Drop table if it exists, then create new one\n-- DROP TABLE IF EXISTS booking_code;\n-- CREATE TABLE booking_code (\n--   id bigserial PRIMARY KEY,\n--   content text, -- corresponds to Document.pageContent\n--   metadata jsonb, -- corresponds to Document.metadata\n--   embedding vector(768) -- 1536 works for OpenAI embeddings, change if needed\n-- );\n\n-- Create a function to search for documents\nCREATE OR REPLACE FUNCTION match_documents (\n  query_embedding vector(768),\n  match_count int DEFAULT NULL,\n  filter jsonb DEFAULT '{}'\n) RETURNS TABLE (\n  id bigint,\n  content text,\n  metadata jsonb,\n  similarity float\n)\nLANGUAGE plpgsql\nAS $$\n#variable_conflict use_column\nBEGIN\n  RETURN QUERY\n  SELECT\n    documents.id,\n    documents.content,\n    documents.metadata,\n    1 - (documents.embedding <=> query_embedding) AS similarity\n  FROM documents\n  LIMIT match_count;\nEND;\n$$;",
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        -704,
        1008
      ],
      "id": "f5199be6-46c7-4ab8-be4e-f3072cf55959",
      "name": "Create Documents Table and Match Function",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "delete",
        "tableId": "document_rows",
        "filters": {
          "conditions": [
            {
              "keyName": "dataset_id",
              "condition": "eq",
              "keyValue": "={{ $('Set File ID2').item.json.file_id }}"
            }
          ]
        }
      },
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        1520,
        848
      ],
      "id": "b2d9f8a3-ab27-49b5-9904-912579150078",
      "name": "Delete Old Data Rows",
      "alwaysOutputData": true,
      "executeOnce": true,
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "disabled": true
    },
    {
      "parameters": {
        "operation": "upsert",
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public"
        },
        "table": {
          "__rl": true,
          "value": "document_metadata",
          "mode": "list",
          "cachedResultName": "document_metadata"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "id": "={{ $('Set File ID2').item.json.file_id }}",
            "title": "={{ $('Set File ID2').item.json.file_title }}",
            "url": "={{ $('Set File ID2').item.json.file_url }}"
          },
          "matchingColumns": [
            "id"
          ],
          "schema": [
            {
              "id": "id",
              "displayName": "id",
              "required": true,
              "defaultMatch": true,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "title",
              "displayName": "title",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": false
            },
            {
              "id": "url",
              "displayName": "url",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": false,
              "removed": false
            },
            {
              "id": "created_at",
              "displayName": "created_at",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "dateTime",
              "canBeUsedToMatch": false
            },
            {
              "id": "schema",
              "displayName": "schema",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": false,
              "removed": true
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        1680,
        848
      ],
      "id": "65f3a165-14c5-4c1f-aa12-4a17ef20cb0b",
      "name": "Insert Document Metadata",
      "executeOnce": true,
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "disabled": true
    },
    {
      "parameters": {
        "jsonMode": "expressionData",
        "jsonData": "={{ $json.text }}",
        "options": {
          "metadata": {
            "metadataValues": [
              {
                "name": "=file_id",
                "value": "={{ $('Set File ID2').first().json.file_id }}"
              },
              {
                "name": "file_title",
                "value": "={{ $('Set File ID2').first().json.file_title }}"
              },
              {
                "name": "page_number",
                "value": "={{ $json.page_number }}"
              },
              {
                "name": "paragraph_type",
                "value": "={{ $json.paragraph_type }}"
              },
              {
                "name": "section_id",
                "value": "={{ $json.section_id }}"
              },
              {
                "name": "section_title",
                "value": "={{$json.section_title}}"
              }
            ]
          }
        }
      },
      "id": "7314cd17-c7e6-48ac-9e1c-b5d3cafc0f91",
      "name": "Default Data Loader2",
      "type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader",
      "typeVersion": 1,
      "position": [
        1648,
        1472
      ]
    },
    {
      "parameters": {
        "chunkSize": 10000
      },
      "id": "69362ff6-80c7-4101-b8b8-667cd042e698",
      "name": "Character Text Splitter2",
      "type": "@n8n/n8n-nodes-langchain.textSplitterCharacterTextSplitter",
      "typeVersion": 1,
      "position": [
        1776,
        1632
      ]
    },
    {
      "parameters": {
        "mode": "insert",
        "tableName": {
          "__rl": true,
          "value": "documents",
          "mode": "list",
          "cachedResultName": "documents"
        },
        "options": {
          "queryName": "match_documents"
        }
      },
      "id": "012497ea-8293-4824-abf8-53d53a5fea6b",
      "name": "Insert into Supabase Vectorstore2",
      "type": "@n8n/n8n-nodes-langchain.vectorStoreSupabase",
      "typeVersion": 1,
      "position": [
        1616,
        1312
      ],
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        32,
        960
      ],
      "id": "51c51a6e-f5aa-4d84-a899-8ebb4b6fd3d7",
      "name": "When clicking \u2018Execute workflow\u2019"
    },
    {
      "parameters": {},
      "type": "@n8n/n8n-nodes-langchain.embeddingsGoogleGemini",
      "typeVersion": 1,
      "position": [
        1536,
        1488
      ],
      "id": "3baf6e8f-bd5c-4c7e-8dca-0c581cf423fa",
      "name": "Embeddings Google Gemini",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {},
      "type": "@n8n/n8n-nodes-langchain.embeddingsGoogleGemini",
      "typeVersion": 1,
      "position": [
        -448,
        448
      ],
      "id": "a96b1a71-c2dc-4025-9787-a26ec788702b",
      "name": "Embeddings Google Gemini1",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "mode": "load",
        "tableName": {
          "__rl": true,
          "value": "documents",
          "mode": "list",
          "cachedResultName": "documents"
        },
        "prompt": "={{ $json.vectorQuery }}",
        "topK": 3,
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.vectorStoreSupabase",
      "typeVersion": 1.3,
      "position": [
        -448,
        272
      ],
      "id": "46ff86b3-abdd-482a-baac-73d08c669565",
      "name": "with preclassification",
      "alwaysOutputData": true,
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "91a79047-f1c3-4b16-921e-0c8a45c43320",
              "name": "chatInput",
              "value": "={{ $json.question }}",
              "type": "string"
            },
            {
              "id": "56cb3f48-70b0-4737-b4cd-8563fdd28455",
              "name": "sessionId",
              "value": "=pureEval-{{ Math.round(Math.random()*1000) }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -288,
        0
      ],
      "id": "9cbd351d-2a7d-4f41-a8a7-afeb0863960d",
      "name": "Eval Input"
    },
    {
      "parameters": {
        "documentId": {
          "__rl": true,
          "value": "YOUR_EVAL_SHEET_ID",
          "mode": "list",
          "cachedResultName": "Public Agentic Arena Evaluation Set",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_EVAL_SHEET_ID/edit?usp=drivesdk"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "list",
          "cachedResultName": "Eval",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_EVAL_SHEET_ID/edit#gid=0"
        },
        "limitRows": true
      },
      "type": "n8n-nodes-base.evaluationTrigger",
      "typeVersion": 4.6,
      "position": [
        -496,
        0
      ],
      "id": "2c37a7c8-3202-4419-9e52-8be1f97009fa",
      "name": "Eval Set",
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "9eab8192-200a-4520-afe9-b13c14cd000c",
              "leftValue": "={{ $json.chatInput }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.filter",
      "typeVersion": 2.2,
      "position": [
        -80,
        0
      ],
      "id": "06841d31-1fc2-4ddb-946b-0ba5ab2cbf46",
      "name": "Filter Empty Rows"
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        288,
        272
      ],
      "id": "d8a7b394-a43d-4cc0-b80e-62c973b6ce35",
      "name": "Agent Output",
      "notesInFlow": true,
      "notes": "Agent Answer => \"json.output\""
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.noOp",
      "name": "Work your Magic here",
      "typeVersion": 1,
      "position": [
        112,
        32
      ],
      "id": "4669c74b-d5ca-459e-ab59-78d061b91f95"
    },
    {
      "parameters": {
        "content": "## Eval Input\n\nCorrect the _Set-Node_ directly to your Agent, once done",
        "height": 288,
        "width": 656,
        "color": 4
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -608,
        -112
      ],
      "typeVersion": 1,
      "id": "18cc4f55-ac8c-4174-9fb8-85f259f640c2",
      "name": "Sticky Note9"
    },
    {
      "parameters": {
        "content": "# https://agentic-arena.app.n8n.cloud/webhook/agentic-arena",
        "height": 80,
        "width": 1056,
        "color": 5
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -768,
        736
      ],
      "typeVersion": 1,
      "id": "140ed324-ca34-4b52-af02-0d31d4205900",
      "name": "Sticky Note10"
    },
    {
      "parameters": {
        "resource": "fileFolder",
        "returnAll": true,
        "filter": {
          "folderId": {
            "__rl": true,
            "value": "YOUR_SOURCE_FOLDER_ID",
            "mode": "list",
            "cachedResultName": "Public Agentic Arena PDF Files",
            "cachedResultUrl": "https://drive.google.com/drive/folders/YOUR_SOURCE_FOLDER_ID"
          }
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleDrive",
      "typeVersion": 3,
      "position": [
        240,
        960
      ],
      "id": "033abe4c-524e-43f6-9c44-857ce87a1ae4",
      "name": "Search files and folders",
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "options": {
          "reset": false
        }
      },
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        912,
        960
      ],
      "id": "cfa8b2dd-936f-4269-ab69-94259bafcd92",
      "name": "Loop Over Items2"
    },
    {
      "parameters": {
        "operation": "download",
        "fileId": {
          "__rl": true,
          "value": "={{ $('Set File ID2').item.json.file_id }}",
          "mode": "id"
        },
        "options": {
          "googleFileConversion": {
            "conversion": {
              "docsToFormat": "text/plain"
            }
          }
        }
      },
      "id": "247e8604-e43d-42c9-a015-811494b7632c",
      "name": "Download File3",
      "type": "n8n-nodes-base.googleDrive",
      "typeVersion": 3,
      "position": [
        1440,
        1040
      ],
      "executeOnce": true,
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "10646eae-ae46-4327-a4dc-9987c2d76173",
              "name": "file_id",
              "value": "={{ $json.id }}",
              "type": "string"
            },
            {
              "id": "f4536df5-d0b1-4392-bf17-b8137fb31a44",
              "name": "file_type",
              "value": "={{ $json.mimeType }}",
              "type": "string"
            },
            {
              "id": "77d782de-169d-4a46-8a8e-a3831c04d90f",
              "name": "file_title",
              "value": "={{ $json.name }}",
              "type": "string"
            },
            {
              "id": "9bde4d7f-e4f3-4ebd-9338-dce1350f9eab",
              "name": "file_url",
              "value": "={{ $json.webViewLink }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "7f0c8a3e-b8e4-4d2c-a4cf-8da3a97c0184",
      "name": "Set File ID2",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1120,
        976
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "186b90da-f161-4f4d-8d94-ac9502f6429b",
              "leftValue": "={{ $json.processingID }}",
              "rightValue": 0,
              "operator": {
                "type": "number",
                "operation": "gte"
              }
            },
            {
              "id": "c41503c0-a340-4617-a615-68b957975fa3",
              "leftValue": "={{ $json.processingID }}",
              "rightValue": 500,
              "operator": {
                "type": "number",
                "operation": "lt"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.filter",
      "typeVersion": 2.2,
      "position": [
        688,
        960
      ],
      "id": "71911476-aa11-493c-ae7b-f7eef7dc23cb",
      "name": "Select Range"
    },
    {
      "parameters": {
        "jsCode": "// First, sort the input items based on the number in the filename\nconst sortedItems = $input.all().sort((a, b) => {\n  // Extract number from filename (assumes format like \"MoF-policy-XX.pdf\")\n  const getNumberFromName = (name) => {\n    const match = name.match(/-(\\d+)\\.pdf$/);\n    return match ? parseInt(match[1], 10) : 0;\n  };\n  \n  const numA = getNumberFromName(a.json.name);\n  const numB = getNumberFromName(b.json.name);\n  \n  return numA - numB;\n});\n\n// Loop over sorted items and add processingID\nlet count = 0;\nfor (const item of sortedItems) {\n  count += 1;\n  item.json.processingID = count;\n}\n\nreturn sortedItems;"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        464,
        960
      ],
      "id": "ae0e5bff-cd15-4652-beaa-fbdbb506dfea",
      "name": "Code in JavaScript"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "0af57e1c-21ab-433b-a109-3e21070857a2",
              "name": "binary_files",
              "value": "={{ $('Download File3').item.binary.data || JSON.parse('{\"message\": \"No binary Attachment\"}') }}",
              "type": "object"
            }
          ]
        },
        "includeOtherFields": true,
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1616,
        1040
      ],
      "id": "0f37d5bf-4c17-4328-866e-9c82d18de72e",
      "name": "Get $('Gmail').item.binary1"
    },
    {
      "parameters": {
        "workflowId": {
          "__rl": true,
          "value": "GtcLjBMusAUB0h30",
          "mode": "list",
          "cachedResultName": "Any-file2json converter"
        },
        "workflowInputs": {
          "mappingMode": "defineBelow",
          "value": {},
          "matchingColumns": [],
          "schema": [
            {
              "id": "binary_files",
              "displayName": "binary_files",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "object"
            },
            {
              "id": "data",
              "displayName": "data",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "object"
            },
            {
              "id": "metadata",
              "displayName": "metadata",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "object"
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        },
        "options": {
          "waitForSubWorkflow": true
        }
      },
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.2,
      "position": [
        1008,
        1248
      ],
      "id": "3dc96728-ce39-4b17-ae2c-5e68a5839813",
      "name": "Execute Workflow1",
      "alwaysOutputData": true
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=Generate a structured json output from PDF-text provided by user.\n\nHerete PDF-text:\n\n{{ $json.data.text }}",
        "hasOutputParser": true,
        "messages": {
          "messageValues": [
            {
              "message": "=You are a Precision OCR Engine. Your task is to strucutre all visible and legible text from PDF with high accuracy and fidelity. Output only the exact text appearing in the input text, maintaining its original case. Preserve the natural reading order (e.g., top-to-bottom, left-to-right). Do not infer, summarize, correct, or add any information not explicitly visible.\n\nSplit up each section\n\nMaintain original line breaks and significant structural spacing where present. If no readable text exists, respond solely with an empty string: \"\". \n\nYour primary objective is an accurate, faithful textual representation of the PDF as structured output JSON."
            }
          ]
        }
      },
      "id": "2597a08e-64ec-417b-9862-54eea9558547",
      "name": "Image-to-text",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        1168,
        1248
      ],
      "typeVersion": 1.4,
      "retryOnFail": true
    },
    {
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n  \"type\": \"object\",\n  \"properties\": {\n    \"paragraphs\": {\n      \"type\": \"array\",\n      \"items\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"action\": {\n            \"type\": \"string\",\n            \"description\": \"Action or parsing instruction\"\n          },\n          \"section_id\": {\n            \"type\": \"string\",\n            \"description\": \"Numbered section identifier only (e.g., '1.1', '2.3.4') - no custom identifiers\"\n          },\n          \"section_title\": {\n            \"type\": \"string\",\n            \"description\": \"Section title (e.g., 'Zone A (Sandbox) Specifications')\"\n          },\n          \"text\": {\n            \"type\": \"string\",\n            \"description\": \"Complete paragraph content including any notes, annotations, or sub-content\"\n          },\n          \"page_number\": {\n            \"type\": \"integer\",\n            \"description\": \"Page number\"\n          },\n          \"paragraph_type\": {\n            \"type\": \"string\",\n            \"description\": \"Type of paragraph (free text)\"\n          }\n        },\n        \"required\": [\"section_id\", \"page_number\"]\n      }\n    }\n  },\n  \"required\": [\"paragraphs\"]\n}"
      },
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "typeVersion": 1.3,
      "position": [
        1312,
        1376
      ],
      "id": "99602cb3-fb30-4193-9d5f-20b17967df46",
      "name": "SO1"
    },
    {
      "parameters": {
        "fieldToSplitOut": "output.paragraphs",
        "options": {}
      },
      "type": "n8n-nodes-base.splitOut",
      "typeVersion": 1,
      "position": [
        1472,
        1312
      ],
      "id": "c5289522-1934-4468-8272-902ecb203095",
      "name": "Split Out1"
    },
    {
      "parameters": {
        "operation": "checkIfEvaluating"
      },
      "type": "n8n-nodes-base.evaluation",
      "typeVersion": 4.7,
      "position": [
        528,
        384
      ],
      "id": "74d14351-79aa-47e2-9426-f4709c5bc802",
      "name": "Only if we are evaluating"
    },
    {
      "parameters": {
        "message": "={{ $json.output }}",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.chat",
      "typeVersion": 1,
      "position": [
        768,
        480
      ],
      "id": "3b76b626-c860-4f43-b042-38f276e30e02",
      "name": "Respond to Chat"
    },
    {
      "parameters": {
        "documentId": {
          "__rl": true,
          "value": "YOUR_EVAL_SHEET_ID",
          "mode": "list",
          "cachedResultName": "Public Agentic Arena Evaluation Set",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_EVAL_SHEET_ID/edit?usp=drivesdk"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "list",
          "cachedResultName": "Eval",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_EVAL_SHEET_ID/edit#gid=0"
        },
        "outputs": {
          "values": [
            {
              "outputName": "correctness",
              "outputValue": "={{ $json.Correctness }}"
            },
            {
              "outputName": "agent answer",
              "outputValue": "={{ $('Edit Fields7').item.json.answer }}"
            }
          ]
        }
      },
      "type": "n8n-nodes-base.evaluation",
      "typeVersion": 4.7,
      "position": [
        1232,
        288
      ],
      "id": "0d08ca25-3efa-4d26-9f87-7553978360a9",
      "name": "Save Eval",
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "setMetrics",
        "expectedAnswer": "={{ $('Eval Set').item.json.answer }}",
        "actualAnswer": "={{$('Edit Fields7').item.json.answer || \"No output provided.\" }}",
        "prompt": "You are an expert factual evaluator assessing the accuracy of answers compared to established ground truths.\n\nEvaluate the factual correctness of a given output compared to the provided ground truth on a scale from 1 to 5. Use detailed reasoning to thoroughly analyze all claims before determining the final score.\n\n# Scoring Criteria\n\n- 5: Highly similar - The output and ground truth are nearly identical, with only minor, insignificant differences.\n- 4: Somewhat similar - The output is largely similar to the ground truth but has few noticeable differences.\n- 3: Moderately similar - There are some evident differences, but the core essence is captured in the output.\n- 2: Slightly similar - The output only captures a few elements of the ground truth and contains several differences.\n- 1: Not similar - The output is significantly different from the ground truth, with few or no matching elements.\n- 0: Not similar at all \u2013 The outpus is completely different from the ground truth or not provided. Like nothings is matching.\n\nEvery correct Citation (ideally exact) inside of the Output that matches the provided ground truth is a strong boost for a good score. Also important: A Citation DOES NOT require to be in square brackets. Correct Text is perfectly fine.\n\n# Evaluation Steps\n\n1. Identify and list the key elements present in both the output and the ground truth.\n2. Compare these key elements to evaluate their similarities and differences, considering both content and structure.\n3. Analyze the semantic meaning conveyed by both the output and the ground truth, noting any significant deviations.\n4. Consider factual accuracy of specific details, including names, dates, numbers, and relationships.\n5. Assess whether the output maintains the factual integrity of the ground truth, even if phrased differently.\n6. Determine the overall level of similarity and accuracy according to the defined criteria.\n7. Check if the Citation of Source is provided and matches the original source of the ground truth.\n\n# Output Format\n\nProvide:\n- A detailed analysis of the comparison (extended reasoning)\n- A one-sentence summary highlighting key differences (not similarities)\n- The final similarity score as an integer (0, 1, 2, 3, 4, or 5)\n\nAlways follow the JSON format below and return nothing else:\n{\n  \"extended_reasoning\": \"<detailed step-by-step analysis of factual accuracy and similarity>\",\n  \"reasoning_summary\": \"<one sentence summary focusing on key differences>\",\n  \"score\": <number: integer from 1 to 5>,\n  \"expected_citation\": \"<exact correct citation of the source like in expected answer>\",\n}\n\n# Examples\n\n**Example 1:**\n\nInput:\n- Output: \"The cat sat on the mat.\"\n- Ground Truth: \"The feline is sitting on the rug.\"\n\nExpected Output:\n{\n  \"extended_reasoning\": \"I need to compare 'The cat sat on the mat' with 'The feline is sitting on the rug.' First, let me identify the key elements: both describe an animal ('cat' vs 'feline') in a position ('sat' vs 'sitting') on a surface ('mat' vs 'rug'). The subject is semantically identical - 'cat' and 'feline' refer to the same animal. The action is also semantically equivalent - 'sat' and 'sitting' both describe the same position, though one is past tense and one is present continuous. The location differs in specific wording ('mat' vs 'rug') but both refer to floor coverings that serve the same function. The basic structure and meaning of both sentences are preserved, though they use different vocabulary and slightly different tense. The core information being conveyed is the same, but there are noticeable wording differences.\",\n  \"reasoning_summary\": \"The sentences differ in vocabulary choice ('cat' vs 'feline', 'mat' vs 'rug') and verb tense ('sat' vs 'is sitting').\",\n  \"score\": 3\n}\n\n**Example 2:**\n\nInput:\n- Output: \"The quick brown fox jumps over the lazy dog.\"\n- Ground Truth: \"A fast brown animal leaps over a sleeping canine.\"\n\nExpected Output:\n{\n  \"extended_reasoning\": \"I need to compare 'The quick brown fox jumps over the lazy dog' with 'A fast brown animal leaps over a sleeping canine.' Starting with the subjects: 'quick brown fox' vs 'fast brown animal'. Both describe the same entity (a fox is a type of animal) with the same attributes (quick/fast and brown). The action is described as 'jumps' vs 'leaps', which are synonymous verbs describing the same motion. The object in both sentences is a dog, described as 'lazy' in one and 'sleeping' in the other, which are related concepts (a sleeping dog could be perceived as lazy). The structure follows the same pattern: subject + action + over + object. The sentences convey the same scene with slightly different word choices that maintain the core meaning. The level of specificity differs slightly ('fox' vs 'animal', 'dog' vs 'canine'), but the underlying information and imagery remain very similar.\",\n  \"reasoning_summary\": \"The sentences use different but synonymous terminology ('quick' vs 'fast', 'jumps' vs 'leaps', 'lazy' vs 'sleeping') and varying levels of specificity ('fox' vs 'animal', 'dog' vs 'canine').\",\n  \"score\": 4\n}\n\n# Notes\n\n- Focus primarily on factual accuracy and semantic similarity, not writing style or phrasing differences.\n- Identify specific differences rather than making general assessments.\n- Pay special attention to dates, numbers, names, locations, and causal relationships when present.\n- Consider the significance of each difference in the context of the overall information.\n- Be consistent in your scoring approach across different evaluations.\n- Value the Citation if correct. False Citation is a negative factor. A missing Citation is strong negative factor.",
        "options": {}
      },
      "type": "n8n-nodes-base.evaluation",
      "typeVersion": 4.7,
      "position": [
        880,
        288
      ],
      "id": "4117277f-86f1-4d2d-a186-dda7eb0de0a9",
      "name": "Run Evaluation"
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "value": "gpt-4.1",
          "mode": "list",
          "cachedResultName": "gpt-4.1"
        },
        "options": {
          "responseFormat": "json_object",
          "temperature": 0.1
        }
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.2,
      "position": [
        1024,
        496
      ],
      "id": "7fbe0333-013f-4881-b6f9-647240a24de6",
      "name": "LLM as a Judge",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "content": "## Eval for Correctness",
        "height": 560,
        "width": 1024,
        "color": 4
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        448,
        96
      ],
      "typeVersion": 1,
      "id": "fcd0e084-74a5-4dad-9061-3b38364bc113",
      "name": "Sticky Note11"
    },
    {
      "parameters": {
        "content": "## Hook up your own GSheet for saving Outputs"
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1264,
        160
      ],
      "typeVersion": 1,
      "id": "cc00f8b9-9a30-4541-bd98-b7305450adb8",
      "name": "Sticky Note12"
    },
    {
      "parameters": {
        "content": "## Do not touch this!\n\n![I see you](https://cloud.let-the-work-flow.com/workflow-data/eval-emoji-72.png)\nSincerely,\n_Pure Eval_",
        "height": 224,
        "color": 3
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1184,
        528
      ],
      "typeVersion": 1,
      "id": "05043233-c9e8-44a8-a34a-126053ef7f8b",
      "name": "Sticky Note13"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=Answer with Yes, No, Multiple plus a explanation.\n<question>\n{{ $('Eval Set').item.json.question }}\n</question>\n\n<vector-result>\n{{ JSON.stringify($input.all()) }}\n</vector-result>",
        "hasOutputParser": true,
        "messages": {
          "messageValues": [
            {
              "message": "write a prompt for the vector search"
            }
          ]
        },
        "batching": {}
      },
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "typeVersion": 1.7,
      "position": [
        -176,
        272
      ],
      "id": "c39c090c-04a9-4df9-aa2a-d0bddca4ede1",
      "name": "Basic LLM Chain2",
      "retryOnFail": true,
      "maxTries": 5
    },
    {
      "parameters": {
        "model": "meta-llama/llama-4-maverick-17b-128e-instruct",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGroq",
      "typeVersion": 1,
      "position": [
        -176,
        464
      ],
      "id": "d14e073a-b0b8-43da-a951-ce8856ff16c3",
      "name": "Groq Chat Model2",
      "credentials": {
        "groqApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n  \"type\": \"object\",\n  \"properties\": {\n    \"main_answer\": {\n      \"type\": \"string\",\n      \"description\": \"Classification response: Yes, No, Multiple\"\n    },\n    \"answers_explanation\": {\n      \"type\": \"string\",\n      \"description\": \"Brief explanation of the answer\"\n    },\n    \"info_source\": {\n      \"type\": \"string\",\n      \"description\": \"Brief explanation of the answer\"\n    },\n    \"required\": [\"main_answer\", \"answers_explanation\", \"info_source\"]\n  }\n}"
      },
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "typeVersion": 1.3,
      "position": [
        -32,
        480
      ],
      "id": "63f9bd8c-b01a-4e33-9cf4-4c522b45e218",
      "name": "Structured Output Parser"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "21af0725-185c-42b6-88bf-b61a2c321125",
              "name": "answer",
              "value": "={{ $json.output.main_answer }} - {{ $json.output.answers_explanation }} /n/n {{$json.output.info_source}}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        112,
        272
      ],
      "id": "d90ac877-fbb3-499b-ad84-8672d7618855",
      "name": "Edit Fields7"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "9a9a245e-f1a1-4282-bb02-a81ffe629f0f",
              "name": "vectorQuery",
              "value": "=# Original Input\n{{ $json.chatInput }}\n",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "fc7da4c2-a8f7-469a-8816-27246e6e6e47",
      "name": "Edit Fields4",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -576,
        272
      ]
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.2,
      "position": [
        1184,
        1488
      ],
      "id": "68486e0f-698e-4341-8d1c-122a2116baf8",
      "name": "OpenAI Chat Model",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "model": "meta-llama/llama-4-maverick-17b-128e-instruct",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGroq",
      "typeVersion": 1,
      "position": [
        1040,
        1536
      ],
      "id": "f9228ba1-8cee-4102-a581-17478f8d271f",
      "name": "Groq Chat Model",
      "credentials": {
        "groqApi": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "Delete Old Doc Rows": {
      "main": [
        [
          {
            "node": "Delete Old Data Rows",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Delete Old Data Rows": {
      "main": [
        [
          {
            "node": "Insert Document Metadata",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Insert Document Metadata": {
      "main": [
        [
          {
            "node": "Download File3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Default Data Loader2": {
      "ai_document": [
        [
          {
            "node": "Insert into Supabase Vectorstore2",
            "type": "ai_document",
            "index": 0
          }
        ]
      ]
    },
    "Character Text Splitter2": {
      "ai_textSplitter": [
        [
          {
            "node": "Default Data Loader2",
            "type": "ai_textSplitter",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \u2018Execute workflow\u2019": {
      "main": [
        [
          {
            "node": "Search files and folders",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Embeddings Google Gemini": {
      "ai_embedding": [
        [
          {
            "node": "Insert into Supabase Vectorstore2",
            "type": "ai_embedding",
            "index": 0
          }
        ]
      ]
    },
    "Embeddings Google Gemini1": {
      "ai_embedding": [
        [
          {
            "node": "with preclassification",
            "type": "ai_embedding",
            "index": 0
          }
        ]
      ]
    },
    "with preclassification": {
      "main": [
        [
          {
            "node": "Basic LLM Chain2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Eval Input": {
      "main": [
        [
          {
            "node": "Filter Empty Rows",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Eval Set": {
      "main": [
        [
          {
            "node": "Eval Input",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Empty Rows": {
      "main": [
        [
          {
            "node": "Work your Magic here",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Work your Magic here": {
      "main": [
        [
          {
            "node": "Edit Fields4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Agent Output": {
      "main": [
        [
          {
            "node": "Only if we are evaluating",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search files and folders": {
      "main": [
        [
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items2": {
      "main": [
        [],
        [
          {
            "node": "Set File ID2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set File ID2": {
      "main": [
        [
          {
            "node": "Delete Old Doc Rows",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Select Range": {
      "main": [
        [
          {
            "node": "Loop Over Items2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript": {
      "main": [
        [
          {
            "node": "Select Range",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download File3": {
      "main": [
        [
          {
            "node": "Get $('Gmail').item.binary1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get $('Gmail').item.binary1": {
      "main": [
        [
          {
            "node": "Execute Workflow1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute Workflow1": {
      "main": [
        [
          {
            "node": "Image-to-text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Image-to-text": {
      "main": [
        [
          {
            "node": "Split Out1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SO1": {
      "ai_outputParser": [
        [
          {
            "node": "Image-to-text",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Split Out1": {
      "main": [
        [
          {
            "node": "Insert into Supabase Vectorstore2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Only if we are evaluating": {
      "main": [
        [
          {
            "node": "Run Evaluation",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond to Chat",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Run Evaluation": {
      "main": [
        [
          {
            "node": "Save Eval",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "LLM as a Judge": {
      "ai_languageModel": [
        [
          {
            "node": "Run Evaluation",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Groq Chat Model2": {
      "ai_languageModel": [
        [
          {
            "node": "Basic LLM Chain2",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Basic LLM Chain2": {
      "main": [
        [
          {
            "node": "Edit Fields7",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Basic LLM Chain2",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Edit Fields7": {
      "main": [
        [
          {
            "node": "Agent Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Fields4": {
      "main": [
        [
          {
            "node": "with preclassification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Insert into Supabase Vectorstore2": {
      "main": [
        [
          {
            "node": "Loop Over Items2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Image-to-text",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    }
  },
  "meta": {
    "templateCredsSetupCompleted": true
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Exact-Recall-Across-Collections. Uses supabase, postgres, documentDefaultDataLoader, textSplitterCharacterTextSplitter. Event-driven trigger; 49 nodes.

Source: https://github.com/runfish5/micro-services/blob/main/projects/n8n/06_exact-recall-across-collections/workflows/exact-recall-across-collections.json — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

My workflow 2529. Uses lmChatOpenAi, documentDefaultDataLoader, embeddingsOpenAi, googleDrive. Event-driven trigger; 54 nodes.

OpenAI Chat, Document Default Data Loader, OpenAI Embeddings +11
AI & RAG

05. Base_To_Copy. Uses lmChatOpenAi, documentDefaultDataLoader, embeddingsOpenAi, googleDrive. Event-driven trigger; 54 nodes.

OpenAI Chat, Document Default Data Loader, OpenAI Embeddings +11
AI & RAG

OIL Rag. Uses lmChatOpenAi, embeddingsOpenAi, agent, telegramTrigger. Event-driven trigger; 53 nodes.

OpenAI Chat, OpenAI Embeddings, Agent +12
AI & RAG

This n8n workflow automates the process of ingesting files from Google Drive into a Supabase database, preparing them for a knowledge base system. It supports text-based files (PDF, DOCX, TXT, etc.) a

Google Drive Trigger, Postgres, Supabase +11
AI & RAG

This template creates a comprehensive, production-ready Retrieval-Augmented Generation (RAG) system. It builds a sophisticated AI agent that can answer questions based on documents stored in a specifi

Reranker Cohere, Supabase Vector Store, Agent +10