Created
December 30, 2025 17:16
-
-
Save unlocomqx/f14b322f8526f759444a95933bddf421 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "nodes": [ | |
| { | |
| "parameters": { | |
| "jsonMode": "expressionData", | |
| "jsonData": "={{ $json.documentation }}", | |
| "textSplittingMode": "custom", | |
| "options": {} | |
| }, | |
| "id": "0a52ad6e-9c9c-415f-b1ec-f1782678cdd5", | |
| "cid": "Ikx1Y2FzIFBleXJpbiI", | |
| "name": "Default Data Loader", | |
| "type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader", | |
| "creator": "Lucas Peyrin", | |
| "position": [ | |
| 1088, | |
| 656 | |
| ], | |
| "typeVersion": 1.1, | |
| "notes": "© 2025 Lucas Peyrin" | |
| }, | |
| { | |
| "parameters": { | |
| "chunkSize": 1500, | |
| "chunkOverlap": 200, | |
| "options": { | |
| "splitCode": "markdown" | |
| } | |
| }, | |
| "id": "50480aec-7bb8-41d1-b569-62ce4c20e251", | |
| "cid": "Ikx1Y2FzIFBleXJpbiI", | |
| "name": "Recursive Character Text Splitter", | |
| "type": "@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter", | |
| "creator": "Lucas Peyrin", | |
| "position": [ | |
| 1184, | |
| 864 | |
| ], | |
| "typeVersion": 1, | |
| "notes": "© 2025 Lucas Peyrin" | |
| }, | |
| { | |
| "parameters": { | |
| "operation": "removeItemsSeenInPreviousExecutions", | |
| "dedupeValue": "={{ $json.documentation }}", | |
| "options": { | |
| "scope": "node", | |
| "historySize": 10000 | |
| } | |
| }, | |
| "id": "e388bdaa-3c42-4512-b4a3-aaaf9a801557", | |
| "cid": "Ikx1Y2FzIFBleXJpbiI", | |
| "name": "Remove Duplicate Documentation Content", | |
| "type": "n8n-nodes-base.removeDuplicates", | |
| "creator": "Lucas Peyrin", | |
| "position": [ | |
| 464, | |
| 432 | |
| ], | |
| "typeVersion": 2, | |
| "notes": "© 2025 Lucas Peyrin" | |
| }, | |
| { | |
| "parameters": { | |
| "assignments": { | |
| "assignments": [ | |
| { | |
| "id": "5ed964a6-5200-454c-b983-f3dc7c8c7a48", | |
| "name": "documentation", | |
| "type": "string", | |
| "value": "={{ $json.data.replace(/([^#\\n]+)\\s*#/g, '# $1').trim().replace(/^\\s*https?:\\/\\/\\S+\\s*/, '') }}" | |
| } | |
| ] | |
| }, | |
| "options": {} | |
| }, | |
| "id": "571b1485-37b1-4e9d-9209-d28db775f36b", | |
| "cid": "Ikx1Y2FzIFBleXJpbiI", | |
| "name": "Clean Documentation", | |
| "type": "n8n-nodes-base.set", | |
| "creator": "Lucas Peyrin", | |
| "position": [ | |
| 48, | |
| 432 | |
| ], | |
| "typeVersion": 3.4, | |
| "notes": "© 2025 Lucas Peyrin" | |
| }, | |
| { | |
| "parameters": { | |
| "url": "=https://dynamic-docs.prestalife.net/{{ $json.link }}", | |
| "options": {} | |
| }, | |
| "id": "6b9db681-67ac-41ef-8b6e-bbd9cb1e8124", | |
| "cid": "Ikx1Y2FzIFBleXJpbiI", | |
| "name": "Get Documentation Page", | |
| "type": "n8n-nodes-base.httpRequest", | |
| "creator": "Lucas Peyrin", | |
| "position": [ | |
| -736, | |
| 432 | |
| ], | |
| "typeVersion": 4.2, | |
| "onError": "continueErrorOutput", | |
| "notes": "© 2025 Lucas Peyrin" | |
| }, | |
| { | |
| "parameters": { | |
| "operation": "extractHtmlContent", | |
| "extractionValues": { | |
| "values": [ | |
| { | |
| "key": "data", | |
| "cssSelector": "main.main" | |
| } | |
| ] | |
| }, | |
| "options": {} | |
| }, | |
| "id": "52dd037a-b55e-49f1-bb51-8eeb2135ad54", | |
| "cid": "Ikx1Y2FzIFBleXJpbiI", | |
| "name": "Extract Documentation Content", | |
| "type": "n8n-nodes-base.html", | |
| "creator": "Lucas Peyrin", | |
| "position": [ | |
| -432, | |
| 432 | |
| ], | |
| "typeVersion": 1.2, | |
| "notes": "© 2025 Lucas Peyrin" | |
| }, | |
| { | |
| "parameters": {}, | |
| "id": "4d18a4f1-be21-4bb7-a746-b85cf4fec9b6", | |
| "cid": "Ikx1Y2FzIFBleXJpbiI", | |
| "name": "Gemini Chunk Embedding", | |
| "type": "@n8n/n8n-nodes-langchain.embeddingsGoogleGemini", | |
| "creator": "Lucas Peyrin", | |
| "position": [ | |
| 960, | |
| 656 | |
| ], | |
| "typeVersion": 1, | |
| "credentials": { | |
| "googlePalmApi": { | |
| "id": "1hVMDAeIReNMOdNs", | |
| "name": "Google Gemini(PaLM) Api account" | |
| } | |
| }, | |
| "notes": "© 2025 Lucas Peyrin" | |
| }, | |
| { | |
| "parameters": { | |
| "content": "### Step 1.5.1: Read a Single Page\n\n**What it does:** This node takes a single URL from the loop and fetches the HTML content of that page.\n**Analogy:** The librarian opens one book to the first page.", | |
| "height": 384, | |
| "width": 288, | |
| "color": 7 | |
| }, | |
| "id": "7a51c18a-0420-4dd6-a1c5-d65a83ff55a4", | |
| "cid": "Ikx1Y2FzIFBleXJpbiI", | |
| "name": "Sticky Note11", | |
| "type": "n8n-nodes-base.stickyNote", | |
| "creator": "Lucas Peyrin", | |
| "position": [ | |
| -832, | |
| 224 | |
| ], | |
| "typeVersion": 1, | |
| "notes": "© 2025 Lucas Peyrin" | |
| }, | |
| { | |
| "parameters": { | |
| "content": "### Why Use a Sub-Workflow?\n\nThe main reason is **memory management**.\n\nProcessing a single web page, especially creating vector embeddings for all its chunks, uses a lot of memory (RAM). The n8n documentation has over 1,000 pages. If we tried to process all of them in a single, linear run, the memory usage would build up with each page and would likely crash your n8n instance.\n\nWhen a sub-workflow finishes its run for one item (one page), n8n **clears out the memory** (RAM) it used before starting the next one.\n\nBy using a sub-workflow, we process pages one-by-one in a memory-efficient loop, making the entire indexing process stable and reliable, even on a massive scale.", | |
| "height": 528, | |
| "width": 512, | |
| "color": 5 | |
| }, | |
| "id": "48371192-892a-4d6d-8dfd-1f4398876d87", | |
| "cid": "Ikx1Y2FzIFBleXJpbiI", | |
| "name": "Sticky Note12", | |
| "type": "n8n-nodes-base.stickyNote", | |
| "creator": "Lucas Peyrin", | |
| "position": [ | |
| -1360, | |
| 80 | |
| ], | |
| "typeVersion": 1, | |
| "notes": "© 2025 Lucas Peyrin" | |
| }, | |
| { | |
| "parameters": { | |
| "content": "### Step 1.5.2: Get the Good Stuff\n\n**What it does:** It extracts only the main text from the article on the page, ignoring menus, footers, and images. Then, it cleans up the formatting.\n**Analogy:** The librarian tears out only the useful pages from the book and cleans up any smudges or messy handwriting.", | |
| "height": 384, | |
| "width": 736, | |
| "color": 7 | |
| }, | |
| "id": "9d378ee6-bcc6-4b44-a3b0-70cbf73752f1", | |
| "cid": "Ikx1Y2FzIFBleXJpbiI", | |
| "name": "Sticky Note13", | |
| "type": "n8n-nodes-base.stickyNote", | |
| "creator": "Lucas Peyrin", | |
| "position": [ | |
| -528, | |
| 224 | |
| ], | |
| "typeVersion": 1, | |
| "notes": "© 2025 Lucas Peyrin" | |
| }, | |
| { | |
| "parameters": { | |
| "content": "### Step 1.5.3: Avoid Re-reading\n\n**What it does:** It checks if we have already processed this exact page content in a previous run. If so, it stops here to save time and resources.\n**Analogy:** The librarian checks their \"already read\" pile to avoid reading the same book twice.\n\n**A Powerful Feature Explained:**\n\nUsually, the \"Remove Duplicates\" node only looks at the items in the *current* execution. But here, it's set to **\"Remove items seen in previous executions.\"**\n\nThis is incredibly powerful in a sub-workflow. Even though our sub-workflow only sees one page at a time, this node has a long-term memory. It remembers every single page it has *ever* processed across all previous runs.\n\nThis makes the workflow robust. You can run the indexing process again and again to update the knowledge base with new documentation, and it will never waste resources re-processing old pages and more importantly, it won't create duplicate chunks in Supabase.", | |
| "height": 608, | |
| "width": 544, | |
| "color": 5 | |
| }, | |
| "id": "fd34238e-f0eb-423d-8d0f-7a59db734219", | |
| "cid": "Ikx1Y2FzIFBleXJpbiI", | |
| "name": "Sticky Note14", | |
| "type": "n8n-nodes-base.stickyNote", | |
| "creator": "Lucas Peyrin", | |
| "position": [ | |
| 240, | |
| 0 | |
| ], | |
| "typeVersion": 1, | |
| "notes": "© 2025 Lucas Peyrin" | |
| }, | |
| { | |
| "parameters": { | |
| "content": "### Step 1.5.4: Create & Store the 'Magic Index Cards'\n\nThis is the most important step of indexing!\n\n1. **`Recursive Character Text Splitter`:** The text is broken down into small, overlapping paragraphs (\"chunks\").\n * **Analogy:** The librarian breaks the book down into small, meaningful paragraphs. This is vital for finding very specific answers later.\n\n2. **`Gemini Chunk Embedding`:** An AI model converts each chunk of text into a list of numbers (a \"vector\" or \"embedding\").\n * **Analogy:** The librarian uses a 'magic pen' to turn each paragraph into a unique set of numbers. Paragraphs with similar meanings get similar numbers.\n\n3. **`Your Supabase Vector Store (Insert)`:** The original text chunk and its new vector are saved together in your Supabase database.\n * **Analogy:** The librarian files the original paragraph along with its magic number on an index card and puts it in a special filing cabinet (your Supabase vector store).", | |
| "height": 1040, | |
| "width": 656, | |
| "color": 6 | |
| }, | |
| "id": "90f31c17-f869-4a07-9ac9-ada55820d927", | |
| "cid": "Ikx1Y2FzIFBleXJpbiI", | |
| "name": "Sticky Note15", | |
| "type": "n8n-nodes-base.stickyNote", | |
| "creator": "Lucas Peyrin", | |
| "position": [ | |
| 800, | |
| 0 | |
| ], | |
| "typeVersion": 1, | |
| "notes": "© 2025 Lucas Peyrin" | |
| }, | |
| { | |
| "parameters": { | |
| "inputSource": "passthrough" | |
| }, | |
| "id": "e28ce8a6-a2f1-4972-942a-1e9c24c37d14", | |
| "cid": "Ikx1Y2FzIFBleXJpbiI", | |
| "name": "Ingest Web Page", | |
| "type": "n8n-nodes-base.executeWorkflowTrigger", | |
| "creator": "Lucas Peyrin", | |
| "position": [ | |
| -1040, | |
| 432 | |
| ], | |
| "typeVersion": 1.1, | |
| "notes": "© 2025 Lucas Peyrin" | |
| }, | |
| { | |
| "parameters": { | |
| "mode": "insert", | |
| "qdrantCollection": { | |
| "__rl": true, | |
| "value": "dp-docs", | |
| "mode": "id" | |
| }, | |
| "options": {} | |
| }, | |
| "type": "@n8n/n8n-nodes-langchain.vectorStoreQdrant", | |
| "typeVersion": 1.3, | |
| "position": [ | |
| 1008, | |
| 432 | |
| ], | |
| "id": "d8e0a22e-e388-4b47-b5f0-dec91b0b0e1b", | |
| "name": "Qdrant Vector Store", | |
| "credentials": { | |
| "qdrantApi": { | |
| "id": "RH3RJkdv3kquotSh", | |
| "name": "QdrantApi account" | |
| } | |
| } | |
| }, | |
| { | |
| "parameters": { | |
| "workflowId": { | |
| "__rl": true, | |
| "value": "UxCYQUrNOlr9AKeK", | |
| "mode": "list", | |
| "cachedResultUrl": "/workflow/UxCYQUrNOlr9AKeK", | |
| "cachedResultName": "Extract Text From Images" | |
| }, | |
| "workflowInputs": { | |
| "mappingMode": "defineBelow", | |
| "value": {} | |
| }, | |
| "options": {} | |
| }, | |
| "type": "n8n-nodes-base.executeWorkflow", | |
| "typeVersion": 1.3, | |
| "position": [ | |
| -176, | |
| 736 | |
| ], | |
| "id": "e2e5d429-abc1-4dcb-8915-36ad25f52385", | |
| "name": "Call 'Extract Text From Images'" | |
| }, | |
| { | |
| "parameters": { | |
| "functionCode": "return [{\n\"json\": {\"link\": \"/fields.html\"}\n}]" | |
| }, | |
| "name": "Set Init-Data", | |
| "type": "n8n-nodes-base.function", | |
| "typeVersion": 1, | |
| "position": [ | |
| -1168, | |
| 752 | |
| ], | |
| "id": "5d3425e4-d5f5-4ab1-a9aa-b6f62963c8f3" | |
| }, | |
| { | |
| "parameters": {}, | |
| "name": "Input Data", | |
| "type": "n8n-nodes-base.noOp", | |
| "typeVersion": 1, | |
| "position": [ | |
| -1024, | |
| 752 | |
| ], | |
| "id": "7f0796d2-eb05-43bd-8e58-2ff332d9ea55" | |
| }, | |
| { | |
| "parameters": {}, | |
| "type": "n8n-nodes-base.manualTrigger", | |
| "typeVersion": 1, | |
| "position": [ | |
| -1360, | |
| 752 | |
| ], | |
| "id": "84f680f0-a5cb-4a9c-9d1f-2f0bc351dee6", | |
| "name": "When clicking ‘Execute workflow’", | |
| "disabled": true | |
| } | |
| ], | |
| "connections": { | |
| "Default Data Loader": { | |
| "ai_document": [ | |
| [ | |
| { | |
| "node": "Qdrant Vector Store", | |
| "type": "ai_document", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Recursive Character Text Splitter": { | |
| "ai_textSplitter": [ | |
| [ | |
| { | |
| "node": "Default Data Loader", | |
| "type": "ai_textSplitter", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Remove Duplicate Documentation Content": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Qdrant Vector Store", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Clean Documentation": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Remove Duplicate Documentation Content", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Get Documentation Page": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Extract Documentation Content", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Extract Documentation Content": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Clean Documentation", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Gemini Chunk Embedding": { | |
| "ai_embedding": [ | |
| [ | |
| { | |
| "node": "Qdrant Vector Store", | |
| "type": "ai_embedding", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Ingest Web Page": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Get Documentation Page", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Call 'Extract Text From Images'": { | |
| "main": [ | |
| [] | |
| ] | |
| }, | |
| "Set Init-Data": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Input Data", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Input Data": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Get Documentation Page", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "When clicking ‘Execute workflow’": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Set Init-Data", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| } | |
| }, | |
| "pinData": {}, | |
| "meta": { | |
| "instanceId": "b925dde278e559e0d490e7389b69917163007b0eac664f344b0338b1a374b734" | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment