{
  "name": "Benchmark LLM performance on legal documents with Google Sheets and OpenRouter",
  "nodes": [
    {
      "id": "17f30fc7-7b73-4588-8d10-27b1a98ea795",
      "name": "When clicking ‘Test workflow’",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -180,
        260
      ]
    },
    {
      "id": "ca19d73c-7c73-4e3d-96cd-842fc0e4f014",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        580,
        500
      ]
    },
    {
      "id": "99b69f4c-e429-40f8-8a22-8ed5fc3c4daa",
      "name": "Merge1",
      "type": "n8n-nodes-base.merge",
      "position": [
        2180,
        420
      ]
    },
    {
      "id": "29d94760-0dd8-4c28-b31e-a499962b14df",
      "name": "Get Tests",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -20,
        260
      ]
    },
    {
      "id": "0853cbfc-f7fc-4097-88f1-1d08504d93d0",
      "name": "Is PDF?",
      "type": "n8n-nodes-base.if",
      "position": [
        140,
        260
      ]
    },
    {
      "id": "dd3eacbb-d93d-4e2d-83ce-7853e16ab00b",
      "name": "Structured Output Parser2",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1800,
        520
      ]
    },
    {
      "id": "ccaf5c92-d95a-4cff-aa19-1f7bd7f1aa0c",
      "name": "Basic LLM Chain1",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        1640,
        340
      ]
    },
    {
      "id": "ae455c78-78aa-4857-bfea-5aed468ce224",
      "name": "Google Drive",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        1220,
        360
      ]
    },
    {
      "id": "d33dc3e9-1f41-44e6-8a95-83c2ab735061",
      "name": "Extract from File",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        1420,
        340
      ]
    },
    {
      "id": "a1b8590f-6ec8-477d-ad8b-b4ca2ffbdd76",
      "name": "Save Input/Output",
      "type": "n8n-nodes-base.set",
      "position": [
        940,
        480
      ]
    },
    {
      "id": "76f8fed7-50d5-42d9-9dda-67a8d547da90",
      "name": "Execute Subworkflow",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        580,
        240
      ]
    },
    {
      "id": "2644c10f-9b1f-4d91-b49e-f3114b3df205",
      "name": "OpenRouter Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        1640,
        520
      ]
    },
    {
      "id": "2d326d74-85c9-4363-b4d6-ee0b2a8abeb3",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        520,
        20
      ],
      "parameters": {
        "width": null,
        "height": 700,
        "content": "## 2. Execute Subworkflow\nThis node runs immediately (batching requests), but waits for the result before moving to the next step."
      }
    },
    {
      "id": "57ee0b46-fb57-48f3-80fb-51d3e1102bdf",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -120,
        460
      ],
      "parameters": {
        "width": 460,
        "height": 280,
        "content": "## Data format\nOur Tests Sheet contains the following columns:\n- ID: A unique identifier for each row\n- Test No.: The test that the LLM was given\n- AI Platform: The LLM that was given the test.\n- Rele"
      }
    },
    {
      "id": "ddfb78af-ff3b-4c83-ac30-b2c36b217eb3",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -40,
        20
      ],
      "parameters": {
        "width": 340,
        "height": 420,
        "content": "## 1. Fetch test cases\nWe start by grabbing our list of test cases stored in a Google Sheet [here](https://docs.google.com/spreadsheets/d/10l_gMtPsge00eTTltGrgvAo54qhh3_twEDsETrQLAGU/edit?usp=sharing)"
      }
    },
    {
      "id": "9d6ee8f0-0d88-4100-bd2a-78bd4439b448",
      "name": "Keep Original Data",
      "type": "n8n-nodes-base.set",
      "position": [
        1440,
        840
      ]
    },
    {
      "id": "d5f9df9c-e94e-4880-89e4-2792a2757256",
      "name": "Sticky Note11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1180,
        20
      ],
      "parameters": {
        "width": 360,
        "height": 540,
        "content": "## 3. Grab the PDF as text\nWe download the PDF from the Google Drive link in the Google Sheet, extracting the file as text for the next step. We filter out any files that do not return data."
      }
    },
    {
      "id": "bab6b7ec-250a-407e-a1b8-c2d1a3e1afec",
      "name": "Sticky Note12",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        840,
        20
      ],
      "parameters": {
        "width": 260,
        "height": 380,
        "content": "## 5. Update results\nWe create a new row in our output sheet, containing our original data together with the judge decision/reasoning."
      }
    },
    {
      "id": "7c0216ab-f5e7-4eb1-a3bd-3c71c72f1c39",
      "name": "Limit (for testing)",
      "type": "n8n-nodes-base.limit",
      "position": [
        360,
        240
      ]
    },
    {
      "id": "7320f4c7-cccb-465d-a103-eb76cc51feb0",
      "name": "Sticky Note13",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1600,
        20
      ],
      "parameters": {
        "width": 360,
        "height": 660,
        "content": "## 4. Judge LLM outputs\nOur prompt judges the LLM input/output and decides if the LLM passed the test. We also ask for a reason why the judge made its decision, which we can use to refine our eval lat"
      }
    },
    {
      "id": "b7d997a9-acf6-415d-a4d3-30a4985f53f7",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -440,
        240
      ],
      "parameters": {
        "width": 180,
        "height": 200,
        "content": "## Start Here\nMake sure to click \"Execute Workflow\" here, rather than underneath, as that will set the webhook in listening mode."
      }
    },
    {
      "id": "de440bcf-2ff2-46fb-958d-158fecc1c451",
      "name": "Sticky Note14",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2120,
        20
      ],
      "parameters": {
        "width": 220,
        "height": 600,
        "content": "## 5. Combine data and return\nReturn the result of the subworkflow back to our HTTP request.\n\nWe are merging our pass/fail + reason together with the original data that was passed in the body of our H"
      }
    },
    {
      "id": "73f53c55-3374-4759-be24-28f54b795886",
      "name": "Update Results",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        920,
        220
      ]
    }
  ],
  "connections": {
    "Is PDF?": {
      "main": [
        [
          {
            "node": "Limit (for testing)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook": {
      "main": [
        [
          {
            "node": "Keep Original Data",
            "type": "main",
            "index": 0
          },
          {
            "node": "Save Input/Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Tests": {
      "main": [
        [
          {
            "node": "Is PDF?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Drive": {
      "main": [
        [
          {
            "node": "Extract from File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Basic LLM Chain1": {
      "main": [
        [
          {
            "node": "Merge1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract from File": {
      "main": [
        [
          {
            "node": "Basic LLM Chain1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save Input/Output": {
      "main": [
        [
          {
            "node": "Google Drive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Keep Original Data": {
      "main": [
        [
          {
            "node": "Merge1",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Execute Subworkflow": {
      "main": [
        [
          {
            "node": "Update Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Limit (for testing)": {
      "main": [
        [
          {
            "node": "Execute Subworkflow",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenRouter Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Basic LLM Chain1",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser2": {
      "ai_outputParser": [
        [
          {
            "node": "Basic LLM Chain1",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "When clicking ‘Test workflow’": {
      "main": [
        [
          {
            "node": "Get Tests",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}