{ "meta": { "instanceId": "workflow-832df7ae", "versionId": "1.0.0", "createdAt": "2025-09-29T07:07:54.300339", "updatedAt": "2025-09-29T07:07:54.300355", "owner": "n8n-user", "license": "MIT", "category": "automation", "status": "active", "priority": "high", "environment": "production" }, "nodes": [ { "id": "0404384b-10b6-4666-84a4-8870db30c607", "name": "Embeddings OpenAI", "type": "n8n-nodes-base.noOp", "position": [ 1220, 280 ], "parameters": { "model": "text-embedding-3-small", "options": {} }, "credentials": { "openAiApi": { "id": "8gccIjcuf3gvaoEr", "name": "OpenAi account" } }, "typeVersion": 1, "notes": "This embeddingsOpenAi node performs automated tasks as part of the workflow." }, { "id": "a6741f04-5a5b-47a9-ac08-eb562f9f6052", "name": "Default Data Loader", "type": "n8n-nodes-base.noOp", "position": [ 1340, 280 ], "parameters": { "options": { "metadata": { "metadataValues": [ { "name": "question", "value": "={{ $json.question }}" }, { "name": "participant", "value": "={{ $json.participant }}" }, { "name": "survey", "value": "={{ $('Get Survey Results').params.documentId.cachedResultName }}" } ] } }, "jsonData": "={{ $json.answer }}", "jsonMode": "expressionData" }, "typeVersion": 1, "notes": "This documentDefaultDataLoader node performs automated tasks as part of the workflow." }, { "id": "7663c3dd-f713-4034-bef6-0c000285f54f", "name": "Convert to Question Answer Pairs", "type": "n8n-nodes-base.set", "position": [ 720, 160 ], "parameters": { "options": {}, "assignments": { "assignments": [ { "id": "6b593ffb-ffbd-4cf5-a508-cd4f2a6d1004", "name": "data", "type": "array", "value": "={{\n Object.keys($json)\n .filter(key => !['row_number', 'Participant'].includes(key))\n .map(key => ({ question: key, answer: $json[key], participant: $json.Participant }))\n}}" } ] } }, "typeVersion": 3.4, "notes": "This set node performs automated tasks as part of the workflow." }, { "id": "84873f0c-81ce-442f-a33c-d7c6c2efa11b", "name": "Recursive Character Text Splitter", "type": "n8n-nodes-base.noOp", "position": [ 1340, 420 ], "parameters": { "options": {} }, "typeVersion": 1, "notes": "This textSplitterRecursiveCharacterTextSplitter node performs automated tasks as part of the workflow." }, { "id": "da9a8ee8-5e3f-49db-8d1f-26a61ca82344", "name": "Get Survey Results", "type": "n8n-nodes-base.googleSheets", "position": [ 540, 160 ], "parameters": { "options": {}, "sheetName": { "__rl": true, "mode": "list", "value": "gid=0", "cachedResultUrl": "{{ $env.WEBHOOK_URL }}", "cachedResultName": "Sheet1" }, "documentId": { "__rl": true, "mode": "list", "value": "1-168Vm-1kCeHkqGLAs6odha4DhPE93njfHlYIviKE50", "cachedResultUrl": "{{ $env.WEBHOOK_URL }}", "cachedResultName": "Remote Working Survey Responses" } }, "credentials": { "googleSheetsOAuth2Api": { "id": "XHvC7jIRR8A2TlUl", "name": "Google Sheets account" } }, "typeVersion": 4.4, "notes": "This googleSheets node performs automated tasks as part of the workflow." }, { "id": "4bad90b2-eefe-49c8-8caa-41cd4cb5e60f", "name": "Get Survey Headers", "type": "n8n-nodes-base.googleSheets", "position": [ 740, 940 ], "parameters": { "options": { "dataLocationOnSheet": { "values": { "range": "A1:Z2", "rangeDefinition": "specifyRangeA1" } } }, "sheetName": { "__rl": true, "mode": "id", "value": "={{ $('Execute Workflow Trigger').first().json.sheetName }}" }, "documentId": { "__rl": true, "mode": "id", "value": "={{ $('Execute Workflow Trigger').first().json.sheetID }}" } }, "credentials": { "googleSheetsOAuth2Api": { "id": "XHvC7jIRR8A2TlUl", "name": "Google Sheets account" } }, "typeVersion": 4.4, "notes": "This googleSheets node performs automated tasks as part of the workflow." }, { "id": "47c64994-9d1f-42ca-a849-3eeab5335b66", "name": "Extract Questions", "type": "n8n-nodes-base.set", "position": [ 940, 940 ], "parameters": { "options": {}, "assignments": { "assignments": [ { "id": "d655b165-dfa2-46cb-bc27-140399bc4227", "name": "question", "type": "array", "value": "={{\n Object.keys($('Get Survey Headers').item.json)\n .filter(key => key.includes('?'))\n}}" } ] } }, "typeVersion": 3.4, "notes": "This set node performs automated tasks as part of the workflow." }, { "id": "c237d523-b290-41ca-b323-4cc7c7f6ff37", "name": "Questions to List", "type": "n8n-nodes-base.splitOut", "position": [ 940, 1120 ], "parameters": { "options": {}, "fieldToSplitOut": "question" }, "typeVersion": 1, "notes": "This splitOut node performs automated tasks as part of the workflow." }, { "id": "7f44a770-4c5d-4404-ae95-d9dee8348380", "name": "Find All Answers", "type": "n8n-nodes-base.httpRequest", "position": [ 1460, 1120 ], "parameters": { "url": "{{ $env.BASE_URL }}", "method": "POST", "options": {}, "jsonBody": "={\n \"limit\": 500,\n \"filter\":{\n \"must\": [\n {\n \"key\": \"metadata.question\",\n \"match\": { \"value\": \"{{ $('For Each Question...').item.json.question }}\" }\n },\n {\n \"key\": \"metadata.survey\",\n \"match\": { \"value\": \"{{ $('Set Variables').item.json.surveyName }}\" }\n }\n ]\n },\n \"with_vector\":true\n}", "sendBody": true, "specifyBody": "json", "authentication": "{{ $credentials.predefinedCredentialType }}", "nodeCredentialType": "YOUR_CREDENTIAL_HERE" }, "credentials": { "qdrantApi": { "id": "NyinAS3Pgfik66w5", "name": "QdrantApi account" } }, "typeVersion": 4.2, "notes": "This httpRequest node performs automated tasks as part of the workflow." }, { "id": "2b6dc317-f8f3-4201-a9e1-d35ee578e79e", "name": "Get Payload of Points", "type": "n8n-nodes-base.httpRequest", "position": [ 2380, 800 ], "parameters": { "url": "{{ $env.BASE_URL }}", "method": "POST", "options": {}, "jsonBody": "={{\n {\n \"ids\": $json.points,\n \"with_payload\": true\n }\n}}", "sendBody": true, "specifyBody": "json", "authentication": "{{ $credentials.predefinedCredentialType }}", "nodeCredentialType": "YOUR_CREDENTIAL_HERE" }, "credentials": { "qdrantApi": { "id": "NyinAS3Pgfik66w5", "name": "QdrantApi account" } }, "typeVersion": 4.2, "notes": "This httpRequest node performs automated tasks as part of the workflow." }, { "id": "d4a37d97-975a-4243-a7ea-81b3e30558a5", "name": "Clusters To List", "type": "n8n-nodes-base.splitOut", "position": [ 2180, 800 ], "parameters": { "options": {}, "fieldToSplitOut": "output" }, "typeVersion": 1, "notes": "This splitOut node performs automated tasks as part of the workflow." }, { "id": "c78f1bf6-8390-48ee-88f4-7d1a893a8ade", "name": "Set Variables", "type": "n8n-nodes-base.set", "position": [ 200, 1060 ], "parameters": { "options": {}, "assignments": { "assignments": [ { "id": "b77c94a0-d865-4bd6-b078-a09b2ddb2a99", "name": "collectionName", "type": "string", "value": "ux_survey_insights" }, { "id": "7b0a4d14-b5f9-4597-84c0-8cfdb363c3d3", "name": "surveyName", "type": "string", "value": "={{ $json.properties.title }}" }, { "id": "45434b3b-3b74-4262-82e0-7ed02155caad", "name": "insightsSheetName", "type": "string", "value": "=Insights-{{ $now.format('yyyyMMdd') }}" } ] } }, "typeVersion": 3.4, "notes": "This set node performs automated tasks as part of the workflow." }, { "id": "fbb1f3c3-06ad-44b5-b020-6fc3c8eda7c4", "name": "OpenAI Chat Model", "type": "n8n-nodes-base.noOp", "position": [ 2560, 980 ], "parameters": { "model": "gpt-4o-mini", "options": {} }, "credentials": { "openAiApi": { "id": "8gccIjcuf3gvaoEr", "name": "OpenAi account" } }, "typeVersion": 1, "notes": "This lmChatOpenAi node performs automated tasks as part of the workflow." }, { "id": "83d3b413-a661-4c4c-9b8d-6ee395a15348", "name": "Prep Output For Export", "type": "n8n-nodes-base.set", "position": [ 3160, 1300 ], "parameters": { "mode": "raw", "options": {}, "jsonOutput": "={{ {\n ...$json.output,\n \"Number of Response\": $('Get Payload of Points').item.json.result.length,\n \"Participant IDs\": $('Get Payload of Points').item.json.result.map(item =>\n item.payload.metadata.participant\n ).join(','),\n \"Raw Responses\": $('Get Payload of Points').item.json.result.map(item =>\n `Participant ${item.payload.metadata.participant},${item.payload.content.replaceAll('\"', '\\\"')}`\n ).join('\\n')\n} }}\n" }, "typeVersion": 3.4, "notes": "This set node performs automated tasks as part of the workflow." }, { "id": "14784dff-a8ea-4b6b-8379-b0c9051a8f98", "name": "Export To Sheets", "type": "n8n-nodes-base.googleSheets", "position": [ 3360, 1300 ], "parameters": { "columns": { "value": {}, "schema": [ { "id": "What is your name?", "type": "string", "display": true, "removed": false, "required": false, "displayName": "What is your name?", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "The responses indicate that two participants have the same name, 'Kwame Nkosi', which suggests a commonality in names or cultural naming traditions among the respondents. This could highlight the importance of understanding cultural context in survey responses.", "type": "string", "display": true, "removed": false, "required": false, "displayName": "The responses indicate that two participants have the same name, 'Kwame Nkosi', which suggests a commonality in names or cultural naming traditions among the respondents. This could highlight the importance of understanding cultural context in survey responses.", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "neutral", "type": "string", "display": true, "removed": false, "required": false, "displayName": "neutral", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "3", "type": "string", "display": true, "removed": false, "required": false, "displayName": "3", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "77,17,54", "type": "string", "display": true, "removed": false, "required": false, "displayName": "77,17,54", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Participant 77,Kwame Nkosi\nParticipant 17,Kwame Nkosi\nParticipant 54,Kwame Nkansah", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Participant 77,Kwame Nkosi\nParticipant 17,Kwame Nkosi\nParticipant 54,Kwame Nkansah", "defaultMatch": false, "canBeUsedToMatch": true } ], "mappingMode": "autoMapInputData", "matchingColumns": [] }, "options": {}, "operation": "append", "sheetName": { "__rl": true, "mode": "name", "value": "={{ $('Set Variables').first().json.insightsSheetName }}" }, "documentId": { "__rl": true, "mode": "id", "value": "={{ $('Execute Workflow Trigger').first().json.sheetID }}" } }, "credentials": { "googleSheetsOAuth2Api": { "id": "XHvC7jIRR8A2TlUl", "name": "Google Sheets account" } }, "typeVersion": 4.4, "notes": "This googleSheets node performs automated tasks as part of the workflow." }, { "id": "779b9411-db3e-44f3-ad2a-c9d40a70580d", "name": "Export To Sheets1", "type": "n8n-nodes-base.googleSheets", "position": [ 2360, 1300 ], "parameters": { "columns": { "value": {}, "schema": [], "mappingMode": "autoMapInputData", "matchingColumns": [] }, "options": {}, "operation": "append", "sheetName": { "__rl": true, "mode": "name", "value": "={{ $('Set Variables').first().json.insightsSheetName }}" }, "documentId": { "__rl": true, "mode": "id", "value": "={{ $('Execute Workflow Trigger').first().json.sheetID }}" } }, "credentials": { "googleSheetsOAuth2Api": { "id": "XHvC7jIRR8A2TlUl", "name": "Google Sheets account" } }, "typeVersion": 4.4, "notes": "This googleSheets node performs automated tasks as part of the workflow." }, { "id": "a31ab677-f57c-4b78-a290-d4a913ed4f8e", "name": "For Each Question...", "type": "n8n-nodes-base.splitInBatches", "position": [ 1280, 940 ], "parameters": { "options": {} }, "typeVersion": 3, "notes": "This splitInBatches node performs automated tasks as part of the workflow." }, { "id": "dcfaf927-6ecd-4ebe-aee0-5fb3367b2725", "name": "Trigger Insights", "type": "n8n-nodes-base.executeWorkflow", "position": [ 1980, 160 ], "parameters": { "options": {}, "workflowId": "={{ $workflow.id }}" }, "typeVersion": 1, "notes": "This executeWorkflow node performs automated tasks as part of the workflow." }, { "id": "2579adf0-9c00-4b87-b53e-740044577ab0", "name": "Prep Values For Trigger", "type": "n8n-nodes-base.set", "position": [ 1800, 160 ], "parameters": { "options": {}, "assignments": { "assignments": [ { "id": "24dd90ad-390f-444e-ba6c-8c06a41e836e", "name": "sheetID", "type": "string", "value": "={{ $('Get Survey Results').params.documentId.value }}" }, { "id": "90199bbb-3938-411c-a7a8-faa7ccba6059", "name": "sheetName", "type": "string", "value": "={{ $('Get Survey Results').params.sheetName.value }}" } ] } }, "executeOnce": true, "typeVersion": 3.4, "notes": "This set node performs automated tasks as part of the workflow." }, { "id": "9b29e850-b9d0-4358-af62-92c20ab3b088", "name": "Execute Workflow Trigger", "type": "n8n-nodes-base.executeWorkflowTrigger", "position": [ 20, 900 ], "parameters": {}, "typeVersion": 1, "notes": "This executeWorkflowTrigger node performs automated tasks as part of the workflow." }, { "id": "70a0dcec-9f74-4af2-bd64-0ab762a77e51", "name": "Create Insights Sheet", "type": "n8n-nodes-base.googleSheets", "position": [ 420, 900 ], "parameters": { "title": "={{ $('Set Variables').first().json.insightsSheetName }}", "options": {}, "operation": "create", "documentId": { "__rl": true, "mode": "id", "value": "={{ $('Execute Workflow Trigger').first().json.sheetID }}" } }, "credentials": { "googleSheetsOAuth2Api": { "id": "XHvC7jIRR8A2TlUl", "name": "Google Sheets account" } }, "typeVersion": 4.4, "alwaysOutputData": true, "notes": "This googleSheets node performs automated tasks as part of the workflow." }, { "id": "f31400fb-dd7a-4c62-90ec-e9d78bbaa5e8", "name": "Prep Values For Export", "type": "n8n-nodes-base.set", "position": [ 2180, 1300 ], "parameters": { "mode": "raw", "options": {}, "jsonOutput": "={\n \"Question\": \"{{ $('For Each Question...').item.json.question }}\",\n \"Insight\": \"No Insight Found\"\n}\n" }, "typeVersion": 3.4, "notes": "This set node performs automated tasks as part of the workflow." }, { "id": "506c20df-5109-422c-8c9e-0eb50fbd3ff9", "name": "Sticky Note", "type": "n8n-nodes-base.stickyNote", "position": [ 459.27570452141345, -42.168106366729035 ], "parameters": { "color": 7, "width": 617.2130261221611, "height": 420.7389587470384, "content": "## Step 1. Import Survey Responses\n[Read more about Google Sheets]({{ $env.WEBHOOK_URL }}\n\nOur approach requires to import all participant responses as vectors with metadata linking them to the questions being answered. To do this, we'll generate questiona and answer pairs from the survey." }, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow." }, { "id": "bddcafa8-6f54-4829-93c9-37bbb9e7edf3", "name": "QA Pairs to List", "type": "n8n-nodes-base.splitOut", "position": [ 900, 160 ], "parameters": { "options": {}, "fieldToSplitOut": "data" }, "typeVersion": 1, "notes": "This splitOut node performs automated tasks as part of the workflow." }, { "id": "8d6e6bf6-c94c-43cb-a29e-5d10207cb8bd", "name": "Sticky Note1", "type": "n8n-nodes-base.stickyNote", "position": [ 1100, -102.05898437632061 ], "parameters": { "color": 7, "width": 563.8350682199533, "height": 678.1641960508446, "content": "## Step 2. Vectorize Each Response Into Qdrant\n[Read more about using Qdrant]({{ $env.WEBHOOK_URL }}\n\nSpecial attention is given to how metadata is captured as it becomes key to this workflow is being able to retrieve subsets of the data for analysis." }, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow." }, { "id": "613d4a32-a87a-423e-a1d1-ee23db0de6d1", "name": "Sticky Note2", "type": "n8n-nodes-base.stickyNote", "position": [ 1680, -30.440883940004255 ], "parameters": { "color": 7, "width": 519.6419932444072, "height": 429.11782776909047, "content": "## Step 3. Trigger Insights SubWorkflow\n[Learn more about Workflow Triggers]({{ $env.WEBHOOK_URL }}\n\nA subworkflow is used to trigger the analysis for the survey. This separation is optional but used here to better demonstrate the two part process." }, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow." }, { "id": "1e858e4a-b91b-4411-8e2a-6eb76647b796", "name": "Sticky Note3", "type": "n8n-nodes-base.stickyNote", "position": [ -57.47778952966382, 710.393394209128 ], "parameters": { "color": 7, "width": 668.3083616841852, "height": 528.2386658883073, "content": "## Step 4. Create Insights Sheet\n[Learn more about Workflow Triggers]({{ $env.WEBHOOK_URL }}\n\nTo capture the generated insights, we'll create a new unique sheet within the survey spreadsheet. This is optional and you may want to capture in other datastores depending on your needs." }, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow." }, { "id": "9170c566-07d3-49dc-aafb-2dbe79940d2c", "name": "Sticky Note4", "type": "n8n-nodes-base.stickyNote", "position": [ 640, 683.5153164275844 ], "parameters": { "color": 7, "width": 536.9288458983389, "height": 622.1362463986454, "content": "## Step 5. Get List Of Questions From Survey\n[Read more about using Google Sheets]({{ $env.WEBHOOK_URL }}\n\nNext we'll fetch the survey for metadata and questions, splitting them into separate workflow items. Our intention is to process each question end-to-end before moving to the next. This approach is a little \"safer\" in the scenario where an interruption occurs we won't lose all our work." }, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow." }, { "id": "8488df77-055d-41cc-94f1-92ac5d54ef10", "name": "Sticky Note5", "type": "n8n-nodes-base.stickyNote", "position": [ 1200, 673.291535602609 ], "parameters": { "color": 7, "width": 823.147012265536, "height": 868.2579789328703, "content": "## Step 6. Find Groups of Similar Answers For Each Question\n[Learn more about using the Code Node]({{ $env.WEBHOOK_URL }}\n\nGiving all the responses to an LLM to analyse is the common but naive approach; the summarisation is usually too high level for real insights and loses a lot of detail such as the number and identity of respondants. What we want to do instead is find and group popular answers for each question to ensure all perspectives are considered.\n\nOur approach does this by mapping our answer vectors to a 2D grid and then identifying where the vector points are \"clustered\"; where a group of points are within close proximity to each other." }, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow." }, { "id": "f4748b6d-5bd8-48cf-942f-3a0dc681078d", "name": "Sticky Note6", "type": "n8n-nodes-base.stickyNote", "position": [ 2060, 1180 ], "parameters": { "color": 7, "width": 536.9288458983389, "height": 359.90385684071794, "content": "## Step 7b. Skip If No Clusters Found\nWhere no clusters were found, it means the answers were unique enough to not show any pattern. eg. \"What's you name?\"" }, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow." }, { "id": "d55d6a47-da8c-46ae-bd10-0eb671dcd121", "name": "Sticky Note7", "type": "n8n-nodes-base.stickyNote", "position": [ 2060, 611.6915003841909 ], "parameters": { "color": 7, "width": 871.451300407926, "height": 541.1135860445843, "content": "## Step 7a. Summarise the Top Groups of Similar Answers\n[Read more about using the Information Extractor Node]({{ $env.WEBHOOK_URL }}\n\nEach discovered cluster will return a reference vector which is used to fetch all related answers in the group.\nThe group is then sent to the LLM to summarise as well as assign a sentiment score." }, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow." }, { "id": "e5d5f88f-5832-43fc-a5b9-f747d08e7e77", "name": "Sticky Note8", "type": "n8n-nodes-base.stickyNote", "position": [ 2620, 1180 ], "parameters": { "color": 7, "width": 924.2798021207429, "height": 363.07347551845976, "content": "## Step 8. Write To Insights Sheet\nFinally, our completed insights to appended to\nthe Insights Sheet we created earlier in the workflow." }, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow." }, { "id": "49ac1504-7b43-4fa1-b4ce-15c7a53c9018", "name": "Sticky Note9", "type": "n8n-nodes-base.stickyNote", "position": [ 460, 400 ], "parameters": { "color": 5, "width": 323.2987132716669, "height": 80, "content": "### Run this once! \nIf for any reason you need to run more than once, be sure to clear the existing data first." }, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow." }, { "id": "450f89c5-ef0f-4bf8-8db9-6347247c7f4d", "name": "Has Clusters?", "type": "n8n-nodes-base.if", "position": [ 1820, 1120 ], "parameters": { "options": {}, "conditions": { "options": { "leftValue": "", "caseSensitive": true, "typeValidation": "strict" }, "combinator": "and", "conditions": [ { "id": "40b6bb62-a2d6-4422-8fbb-7ae49898bad9", "operator": { "type": "array", "operation": "notEmpty", "singleValue": true }, "leftValue": "={{ $json.output }}", "rightValue": "" } ] } }, "typeVersion": 2, "notes": "This if node performs automated tasks as part of the workflow." }, { "id": "1652a108-8fb8-4229-a76d-abf9fbcff626", "name": "Sticky Note10", "type": "n8n-nodes-base.stickyNote", "position": [ 20, -400 ], "parameters": { "width": 400.381109509268, "height": 679.5610243514676, "content": "## Try It Out!\n\n### This workflow generates highly-detailed insights from survey responses. Works best when dealing with a large number of participants.\n\n* Import survey responses and vectorise in Qdrant vectorstore.\n* Identify clusters of popular responses to questions using K-means clustering algorithm. \n* Each valid cluster is analysed and summarised by LLM.\n* Export LLM response and cluster results back into sheet.\n\nCheck out the reference google sheet here: {{ $env.WEBHOOK_URL }}\n\n### Need Help?\nJoin the [Discord]({{ $env.WEBHOOK_URL }} or ask in the [Forum]({{ $env.WEBHOOK_URL }}\n\nHappy Hacking!" }, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow." }, { "id": "6eef981e-b2ce-433c-b71f-78be64812a56", "name": "Sticky Note11", "type": "n8n-nodes-base.stickyNote", "position": [ 1260, 1340 ], "parameters": { "color": 5, "width": 323.2987132716669, "height": 110.05160146874424, "content": "### First Time Running?\nThere is a slight delay on first run because the code node has to download the required packages." }, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow." }, { "id": "fa0c14be-03f4-4ed2-bd60-e93817382ded", "name": "When clicking ‘Test workflow’", "type": "n8n-nodes-base.manualTrigger", "position": [ 240, 100 ], "parameters": {}, "typeVersion": 1, "notes": "This manualTrigger node performs automated tasks as part of the workflow." }, { "id": "30323019-59ba-4a19-a46e-196d469f097d", "name": "Get Sheet Details", "type": "n8n-nodes-base.httpRequest", "position": [ 200, 900 ], "parameters": { "url": "{{ $env.BASE_URL }}", "options": {}, "authentication": "{{ $credentials.predefinedCredentialType }}", "nodeCredentialType": "YOUR_CREDENTIAL_HERE" }, "credentials": { "googleSheetsOAuth2Api": { "id": "XHvC7jIRR8A2TlUl", "name": "Google Sheets account" } }, "typeVersion": 4.2, "notes": "This httpRequest node performs automated tasks as part of the workflow." }, { "id": "6ced8012-1dd3-4da3-8c27-e4f4dfc959f6", "name": "Only Clusters With 3+ points", "type": "n8n-nodes-base.filter", "position": [ 2180, 960 ], "parameters": { "options": {}, "conditions": { "options": { "leftValue": "", "caseSensitive": true, "typeValidation": "strict" }, "combinator": "and", "conditions": [ { "id": "328f806c-0792-4d90-9bee-a1e10049e78f", "operator": { "type": "array", "operation": "lengthGt", "rightType": "number" }, "leftValue": "={{ $json.points }}", "rightValue": 2 } ] } }, "typeVersion": 2, "notes": "This filter node performs automated tasks as part of the workflow." }, { "id": "8ae81a55-75e2-40a3-bef6-0935ff08128f", "name": "Apply K-means Clustering Algorithm", "type": "n8n-nodes-base.code", "position": [ 1640, 1120 ], "parameters": { "language": "python", "pythonCode": "import numpy as np\nfrom sklearn.cluster import KMeans\n\n# get vectors for all answers\npoint_ids = [item.id for item in _input.first().json.result.points]\nvectors = [item.vector.to_py() for item in _input.first().json.result.points]\nvectors_array = np.array(vectors)\n\n# apply k-means clustering where n_clusters = 10\n# this is a max and we'll discard some of these clusters later\nkmeans = KMeans(n_clusters=min(len(vectors), 10), random_state=42).fit(vectors_array)\nlabels = kmeans.labels_\nunique_labels = set(labels)\n\n# Extract and print points in each cluster\nclusters = {}\nfor label in set(labels):\n clusters[label] = vectors_array[labels == label]\n\n# return Qdrant point ids for each cluster\n# we'll use these ids to fetch the payloads from the vector store.\noutput = []\nfor cluster_id, cluster_points in clusters.items():\n points = [point_ids[i] for i in range(len(labels)) if labels[i] == cluster_id]\n output.append({\n \"id\": f\"Cluster {cluster_id}\",\n \"total\": len(cluster_points),\n \"points\": points\n })\n\nreturn {\"json\": {\"output\": output } }" }, "typeVersion": 2, "notes": "This code node performs automated tasks as part of the workflow." }, { "id": "cbb42384-d46b-471f-a7d8-27e3de042492", "name": "Qdrant Vector Store", "type": "n8n-nodes-base.noOp", "position": [ 1220, 100 ], "parameters": { "mode": "insert", "options": {}, "qdrantCollection": { "__rl": true, "mode": "list", "value": "ux_survey_insights", "cachedResultName": "ux_survey_insights" } }, "credentials": { "qdrantApi": { "id": "NyinAS3Pgfik66w5", "name": "QdrantApi account" } }, "typeVersion": 1, "notes": "This vectorStoreQdrant node performs automated tasks as part of the workflow." }, { "id": "17584901-15d6-421f-ad69-3ba872276055", "name": "Survey Insights Agent", "type": "n8n-nodes-base.noOp", "position": [ 2580, 800 ], "parameters": { "text": "=The {{ $json.result.length }} participant responses were:\n{{\n$json.result.map(item =>\n`* Participant ${item.payload.metadata.participant}: \"${item.payload.content.replaceAll('\"', '\\\"')}\"`\n).join('\\n')\n}}", "options": { "systemPromptTemplate": "=You help summarise a selection of participant responses to a specific question for a survey called \"{{ $json.result[0].payload.metadata.survey }}\".\nThe question asked was \"{{ $json.result[0].payload.metadata.question }}\".\nThe {{ $json.result.length }} participant responses were selected because their answers were similar in context.\n\nYour task is to: \n* summarise the given participant responses into a short paragraph. Provide an insight from this summary and what we could learn from the answers.\n* determine if the overall sentiment of all the listed responses to be either negative, mildy negative, neutral, mildy positive or positive." }, "schemaType": "fromJson", "jsonSchemaExample": "{\n\t\"Question\": \"What do you enjoy most about working remotely, and why?\",\n\t\"Insight\": \"\",\n \"Sentiment\": \"Positive\"\n}" }, "typeVersion": 1, "notes": "This informationExtractor node performs automated tasks as part of the workflow." } ], "pinData": {}, "connections": { "7f44a770-4c5d-4404-ae95-d9dee8348380": { "main": [ [ { "node": "error-handler-7f44a770-4c5d-4404-ae95-d9dee8348380", "type": "main", "index": 0 } ], [ { "node": "error-handler-7f44a770-4c5d-4404-ae95-d9dee8348380-41bcee4c", "type": "main", "index": 0 } ], [ { "node": "error-handler-7f44a770-4c5d-4404-ae95-d9dee8348380-d0c11290", "type": "main", "index": 0 } ], [ { "node": "error-handler-7f44a770-4c5d-4404-ae95-d9dee8348380-dd354e9c", "type": "main", "index": 0 } ], [ { "node": "error-handler-7f44a770-4c5d-4404-ae95-d9dee8348380-ac31ce8a", "type": "main", "index": 0 } ], [ { "node": "error-handler-7f44a770-4c5d-4404-ae95-d9dee8348380-7bb82304", "type": "main", "index": 0 } ], [ { "node": "error-handler-7f44a770-4c5d-4404-ae95-d9dee8348380-5c7a3313", "type": "main", "index": 0 } ], [ { "node": "error-handler-7f44a770-4c5d-4404-ae95-d9dee8348380-8f7cebc6", "type": "main", "index": 0 } ], [ { "node": "error-handler-7f44a770-4c5d-4404-ae95-d9dee8348380-9774f7cb", "type": "main", "index": 0 } ] ] }, "2b6dc317-f8f3-4201-a9e1-d35ee578e79e": { "main": [ [ { "node": "error-handler-2b6dc317-f8f3-4201-a9e1-d35ee578e79e", "type": "main", "index": 0 } ], [ { "node": "error-handler-2b6dc317-f8f3-4201-a9e1-d35ee578e79e-be0723c4", "type": "main", "index": 0 } ], [ { "node": "error-handler-2b6dc317-f8f3-4201-a9e1-d35ee578e79e-bbe814c5", "type": "main", "index": 0 } ], [ { "node": "error-handler-2b6dc317-f8f3-4201-a9e1-d35ee578e79e-50420ae1", "type": "main", "index": 0 } ], [ { "node": "error-handler-2b6dc317-f8f3-4201-a9e1-d35ee578e79e-8d46b60a", "type": "main", "index": 0 } ], [ { "node": "error-handler-2b6dc317-f8f3-4201-a9e1-d35ee578e79e-be1e1809", "type": "main", "index": 0 } ], [ { "node": "error-handler-2b6dc317-f8f3-4201-a9e1-d35ee578e79e-4cac58f3", "type": "main", "index": 0 } ], [ { "node": "error-handler-2b6dc317-f8f3-4201-a9e1-d35ee578e79e-0487b45b", "type": "main", "index": 0 } ], [ { "node": "error-handler-2b6dc317-f8f3-4201-a9e1-d35ee578e79e-0d80ffef", "type": "main", "index": 0 } ] ] }, "30323019-59ba-4a19-a46e-196d469f097d": { "main": [ [ { "node": "error-handler-30323019-59ba-4a19-a46e-196d469f097d", "type": "main", "index": 0 } ], [ { "node": "error-handler-30323019-59ba-4a19-a46e-196d469f097d-d493827c", "type": "main", "index": 0 } ], [ { "node": "error-handler-30323019-59ba-4a19-a46e-196d469f097d-f13e2598", "type": "main", "index": 0 } ], [ { "node": "error-handler-30323019-59ba-4a19-a46e-196d469f097d-696e053a", "type": "main", "index": 0 } ], [ { "node": "error-handler-30323019-59ba-4a19-a46e-196d469f097d-76f17e46", "type": "main", "index": 0 } ], [ { "node": "error-handler-30323019-59ba-4a19-a46e-196d469f097d-cb2708a7", "type": "main", "index": 0 } ], [ { "node": "error-handler-30323019-59ba-4a19-a46e-196d469f097d-e6be6faa", "type": "main", "index": 0 } ], [ { "node": "error-handler-30323019-59ba-4a19-a46e-196d469f097d-ae50879d", "type": "main", "index": 0 } ], [ { "node": "error-handler-30323019-59ba-4a19-a46e-196d469f097d-a56c21ce", "type": "main", "index": 0 } ] ] }, "0404384b-10b6-4666-84a4-8870db30c607": { "main": [ [ { "node": "error-handler-0404384b-10b6-4666-84a4-8870db30c607-bca7a6fa", "type": "main", "index": 0 } ] ] }, "da9a8ee8-5e3f-49db-8d1f-26a61ca82344": { "main": [ [ { "node": "error-handler-da9a8ee8-5e3f-49db-8d1f-26a61ca82344-8294d8cb", "type": "main", "index": 0 } ] ] }, "4bad90b2-eefe-49c8-8caa-41cd4cb5e60f": { "main": [ [ { "node": "error-handler-4bad90b2-eefe-49c8-8caa-41cd4cb5e60f-5a75651e", "type": "main", "index": 0 } ] ] }, "fbb1f3c3-06ad-44b5-b020-6fc3c8eda7c4": { "main": [ [ { "node": "error-handler-fbb1f3c3-06ad-44b5-b020-6fc3c8eda7c4-739bdd0f", "type": "main", "index": 0 } ] ] }, "14784dff-a8ea-4b6b-8379-b0c9051a8f98": { "main": [ [ { "node": "error-handler-14784dff-a8ea-4b6b-8379-b0c9051a8f98-761d0210", "type": "main", "index": 0 } ] ] }, "779b9411-db3e-44f3-ad2a-c9d40a70580d": { "main": [ [ { "node": "error-handler-779b9411-db3e-44f3-ad2a-c9d40a70580d-1cbf525c", "type": "main", "index": 0 } ] ] }, "70a0dcec-9f74-4af2-bd64-0ab762a77e51": { "main": [ [ { "node": "error-handler-70a0dcec-9f74-4af2-bd64-0ab762a77e51-7e4e8a13", "type": "main", "index": 0 } ] ] } }, "name": "Embeddingsopenai Workflow", "settings": { "executionOrder": "v1", "saveManualExecutions": true, "callerPolicy": "workflowsFromSameOwner", "errorWorkflow": null, "timezone": "UTC", "executionTimeout": 3600, "maxExecutions": 1000, "retryOnFail": true, "retryCount": 3, "retryDelay": 1000 }, "description": "Automated workflow: Embeddingsopenai Workflow. This workflow integrates 19 different services: stickyNote, textSplitterRecursiveCharacterTextSplitter, vectorStoreQdrant, lmChatOpenAi, executeWorkflow. It contains 55 nodes and follows best practices for error handling and security.", "tags": [ "automation", "n8n", "production-ready", "excellent", "optimized" ], "notes": "Excellent quality workflow: Embeddingsopenai Workflow. This workflow has been optimized for production use with comprehensive error handling, security, and documentation." }