AutomationFlowsAI & RAG › Document Q&a System with Voyage-context-3 Embeddings and Mongodb Atlas

Document Q&a System with Voyage-context-3 Embeddings and Mongodb Atlas

ByJimleuk @jimleuk on n8n.io

On my never-ending quest to find the best embeddings model, I was intrigued to come across Voyage-Context-3 by MongoDB and was excited to give it a try.

Event trigger★★★★★ complexityAI-powered53 nodesHTTP RequestExecute Workflow TriggerMongoDBOpenAI ChatInformation ExtractorChat TriggerChatOpenAI
AI & RAG Trigger: Event Nodes: 53 Complexity: ★★★★★ AI nodes: yes Added:

This workflow corresponds to n8n.io template #6819 — we link there as the canonical source.

This workflow follows the Chat → Chat Trigger 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
{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "cc8db825-4ae4-4795-b3d3-a858af3d62c7",
      "name": "When clicking \u2018Execute workflow\u2019",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -320,
        -336
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "37a7e1ab-e3f3-4588-92a9-6a3bdf4335dc",
      "name": "Import Research Paper",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        336,
        -336
      ],
      "parameters": {
        "url": "={{ $('Set Variables').first().json.url }}",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "34c48356-2d29-41a2-902b-9512bb9bf3c8",
      "name": "Extract from File",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        512,
        -336
      ],
      "parameters": {
        "options": {
          "joinPages": false
        },
        "operation": "pdf"
      },
      "typeVersion": 1
    },
    {
      "id": "7a1609c6-19f7-41e0-9054-aa10d31e4529",
      "name": "Split Pages",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        688,
        -336
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "text"
      },
      "typeVersion": 1
    },
    {
      "id": "bbb632c2-a98c-4727-82f1-7a2ddd6cab89",
      "name": "Page Ref",
      "type": "n8n-nodes-base.noOp",
      "position": [
        1808,
        0
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "9bb0b5a0-bc3a-4d56-92cb-9287f6dd18f3",
      "name": "Chunk Page Text",
      "type": "n8n-nodes-base.code",
      "position": [
        2096,
        -208
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const chunks = [];\nconst chunkSize = 1000;\nconst chunkOverlap = 0; // Voyage recommends no overlap for contextual embeddings\nconst text = $input.item.json.text.replace(/\\n/, '');\n\nfor (let i=0,j=Math.round(text.length/chunkSize)+1;i<j;i++) {\n  chunks.push(\n    text.substr(\n      Math.max(0,(i * chunkSize)-chunkOverlap),\n      chunkSize\n    )\n  );\n}\n\nreturn { chunks };"
      },
      "typeVersion": 2
    },
    {
      "id": "cbe2e982-7c4a-48e7-aa2a-3b9615d41deb",
      "name": "Voyage-Context-3 Embeddings",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2288,
        -208
      ],
      "parameters": {
        "url": "https://api.voyageai.com/v1/contextualizedembeddings",
        "method": "POST",
        "options": {},
        "jsonBody": "={{\n{\n  \"inputs\": $input.all().map(item => item.json.chunks.compact()),\n  \"input_type\": \"document\",\n  \"model\": \"voyage-context-3\"\n}\n}}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "executeOnce": true,
      "typeVersion": 4.2
    },
    {
      "id": "dfd6df48-a0a6-4995-925b-6dbe8dd58747",
      "name": "Split Out",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        2480,
        -208
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "data"
      },
      "typeVersion": 1
    },
    {
      "id": "4dcbc327-0880-4f3b-9ba1-f6951f95b988",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        1584,
        0
      ],
      "parameters": {
        "options": {},
        "batchSize": 3
      },
      "typeVersion": 3
    },
    {
      "id": "19775d9b-fe97-4078-8ef5-252f45796e2c",
      "name": "Combine Content & Vectors",
      "type": "n8n-nodes-base.set",
      "position": [
        3184,
        -208
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "bba20778-dbf9-459b-a1aa-97a76ba01713",
              "name": "text",
              "type": "string",
              "value": "={{ $('Chunk Page Text').all()[$runIndex].json.chunks[$itemIndex] }}"
            },
            {
              "id": "20069d1a-4893-4823-9b39-9c61e2e88bee",
              "name": "embeddings",
              "type": "array",
              "value": "={{ $json.embedding }}"
            },
            {
              "id": "26d237a5-5991-4deb-867d-07b5bda6d2c2",
              "name": "metadata",
              "type": "object",
              "value": "={{\n{\n  \"pageNumber\": $('Page Ref').first().json.pageNumber,\n  \"url\": $('Page Ref').first().json.url\n}\n}}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "98e580fe-8db3-4e9d-bffd-1034cc8e61a1",
      "name": "Subworkflow Trigger",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "position": [
        1360,
        0
      ],
      "parameters": {
        "workflowInputs": {
          "values": [
            {
              "name": "text"
            },
            {
              "name": "url"
            },
            {
              "name": "pageNumber",
              "type": "number"
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "206e4cc4-693f-40df-8c37-45822dd953b5",
      "name": "Batch 10",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        1216,
        -336
      ],
      "parameters": {
        "options": {},
        "batchSize": 10
      },
      "typeVersion": 3
    },
    {
      "id": "2460bcd5-950a-4fbd-96eb-5428e03a32fb",
      "name": "Call Embeddings Subworkflow",
      "type": "n8n-nodes-base.executeWorkflow",
      "position": [
        1440,
        -336
      ],
      "parameters": {
        "options": {
          "waitForSubWorkflow": true
        },
        "workflowId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $workflow.id }}"
        },
        "workflowInputs": {
          "value": {
            "url": "={{ $('Set Variables').first().json.url }}",
            "text": "={{ $json.text }}",
            "pageNumber": "={{ $json.pageNumber }}"
          },
          "schema": [
            {
              "id": "text",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "text",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "url",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "pageNumber",
              "type": "number",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "pageNumber",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "page"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "f044e091-b50c-4686-9f0a-e0abeb1022a0",
      "name": "Done",
      "type": "n8n-nodes-base.set",
      "position": [
        4016,
        0
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "e2c34b5b-2a3e-4fcd-a639-4d72368b783a",
              "name": "response",
              "type": "string",
              "value": "ok"
            }
          ]
        }
      },
      "executeOnce": true,
      "typeVersion": 3.4
    },
    {
      "id": "e52fa239-18e7-4ea9-93d2-010dd3555fa6",
      "name": "Voyage-Context-3 Embeddings1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1328,
        528
      ],
      "parameters": {
        "url": "https://api.voyageai.com/v1/contextualizedembeddings",
        "method": "POST",
        "options": {},
        "jsonBody": "={{\n{\n  \"inputs\": [\n    [\n      $('Get Query').first().json.query\n      + ' '\n      + $('Aggregate Answers').item.json.answers.map(item => item.chatInput).join(' ')\n    ]\n  ],\n  \"input_type\": \"query\",\n  \"model\": \"voyage-context-3\"\n}\n}}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "executeOnce": false,
      "typeVersion": 4.2
    },
    {
      "id": "6f3c7ef8-891e-4dd4-bbf0-4adf6e193532",
      "name": "Perform Similarity Search",
      "type": "n8n-nodes-base.mongoDb",
      "position": [
        1520,
        528
      ],
      "parameters": {
        "query": "={{\n([\n  {\n    \"$vectorSearch\": {\n      \"index\": \"vector_index\",\n      \"path\": \"embeddings\",\n      \"queryVector\": $json.data[0].data[0].embedding,\n      \"numCandidates\": 150,\n      \"limit\": 10\n    }\n  },\n  {\n    \"$project\": {\n      \"_id\": 0,\n      \"text\": 1,\n      \"metadata\": 1,\n      \"score\": {\n        \"$meta\": \"vectorSearchScore\"\n      }\n    }\n  }\n]).toJsonString()\n}}",
        "operation": "aggregate",
        "collection": "documents"
      },
      "credentials": {
        "mongoDb": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "1a41d58f-b8fc-498f-a807-ffc3edd400ed",
      "name": "Add Page Number",
      "type": "n8n-nodes-base.set",
      "position": [
        848,
        -336
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "3103cd6a-5932-432a-8859-7dd14d496258",
              "name": "pageNumber",
              "type": "number",
              "value": "={{ $itemIndex + 1 }}"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "5af13dae-29e2-4f6f-a8e8-96cf9d01569e",
      "name": "Set Variables",
      "type": "n8n-nodes-base.set",
      "position": [
        -144,
        -336
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "7ff25027-cfa5-4f63-8b13-05a724c5bb96",
              "name": "url",
              "type": "string",
              "value": "https://arxiv.org/pdf/2402.06196"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "e57a9115-5bb4-469b-9e1c-57e8747c9e79",
      "name": "Wait",
      "type": "n8n-nodes-base.wait",
      "position": [
        1664,
        -336
      ],
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "5877e228-c02c-41c1-9fd5-a76f47414ba0",
      "name": "Get Query",
      "type": "n8n-nodes-base.set",
      "position": [
        -80,
        528
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a197e69a-0f22-45ab-9b57-535e80fe12af",
              "name": "query",
              "type": "string",
              "value": "={{ $json.chatInput }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "60f7b22e-e56e-43c6-9651-c36d6bb6fa17",
      "name": "Aggregate",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        1712,
        528
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "d0a430ed-c2a2-4331-98b7-b1929cfe591f",
      "name": "Query Ref",
      "type": "n8n-nodes-base.noOp",
      "position": [
        800,
        704
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "fe490208-25a9-4504-97b8-bbf3ce3e0b60",
      "name": "Loop Over Questions",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        592,
        528
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "f30d70b4-42d3-48f4-b44d-0f48dd2d459a",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        176,
        672
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "609d43c1-e536-49c7-8470-2c23763302ec",
      "name": "Generate Clarifying Questions",
      "type": "@n8n/n8n-nodes-langchain.informationExtractor",
      "position": [
        96,
        528
      ],
      "parameters": {
        "text": "={{ $json.query }}",
        "options": {
          "systemPromptTemplate": "You are a helpful assistant helping a user research a paper titled \"Large Language Models: A Survey\".\n\nYour task is to generate 2 clarifying questions for the user's query so that later search queries can be better refined."
        },
        "schemaType": "manual",
        "inputSchema": "{\n\t\"type\": \"object\",\n    \"required\": [\"questions\"],\n\t\"properties\": {\n\t\t\"questions\": {\n\t\t\t\"type\": \"array\",\n\t\t\t\"items\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t}\n\t\t}\n\t}\n}"
      },
      "typeVersion": 1.2
    },
    {
      "id": "35132610-83bb-4582-ad42-8e3954ea234f",
      "name": "Split Questions",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        400,
        528
      ],
      "parameters": {
        "options": {
          "destinationFieldName": "question"
        },
        "fieldToSplitOut": "output.questions"
      },
      "typeVersion": 1
    },
    {
      "id": "70b2e1bb-c868-4adc-b21a-a9e95d166198",
      "name": "When chat message received",
      "type": "@n8n/n8n-nodes-langchain.chatTrigger",
      "position": [
        -336,
        528
      ],
      "parameters": {
        "public": true,
        "options": {
          "responseMode": "responseNodes"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "5cba1271-764b-48ea-81b8-1bf5f2b2f813",
      "name": "Wait for Answer",
      "type": "@n8n/n8n-nodes-langchain.chat",
      "position": [
        992,
        704
      ],
      "parameters": {
        "message": "={{ $json.question }}",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "581a9f27-dc41-40c2-8d91-ace13e3675a0",
      "name": "Quick Confirmation",
      "type": "@n8n/n8n-nodes-langchain.chat",
      "position": [
        992,
        528
      ],
      "parameters": {
        "message": "Thanks. Please wait whilst I search the relevant document.",
        "options": {},
        "waitUserReply": false
      },
      "typeVersion": 1
    },
    {
      "id": "0c9b0917-b3c2-4c8d-9825-1db4e07b8449",
      "name": "Aggregate Answers",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        800,
        528
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "answers"
      },
      "typeVersion": 1
    },
    {
      "id": "ea32ae52-d7ec-4f35-8ef8-04842d3cce72",
      "name": "Respond to User",
      "type": "@n8n/n8n-nodes-langchain.chat",
      "position": [
        2640,
        528
      ],
      "parameters": {
        "message": "={{ $json.message.content.answer }}",
        "options": {},
        "waitUserReply": false
      },
      "typeVersion": 1
    },
    {
      "id": "931f6b89-1c5a-4865-a0cc-3264795ef498",
      "name": "RAG Agent",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        2304,
        528
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini",
          "cachedResultName": "GPT-4.1-MINI"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "role": "system",
              "content": "=You are a helpful assistant. The user session involves answering user question against a research paper. Refer and use only the <documents> context to answer the user questions."
            },
            {
              "role": "assistant",
              "content": "=<documents>{{ $json.data.toJsonString() }}</document>"
            },
            {
              "content": "={{\n$('Get Query').first().json.query\n    + ' '\n    + $('Aggregate Answers').first().json.answers.map(item => item.chatInput).join(' ')\n}}"
            }
          ]
        },
        "jsonOutput": true
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "9ded06c0-e7a1-4c5e-82c8-a432347b7b90",
      "name": "Fetch Document By Page Number",
      "type": "n8n-nodes-base.mongoDbTool",
      "position": [
        2384,
        672
      ],
      "parameters": {
        "query": "={\n    \"metadata.pageNumber\": {{ $fromAI(\"pageNumber\", \"the page number to fetch\", \"number\") }}\n    \"embedding\": { \"$exists\": false } // Second condition: ensure 'embedding' key does not exist\n  },\n  {\n    \"text\": 1,\n    \"metadata\": 1\n  }",
        "options": {},
        "collection": "documents",
        "descriptionType": "manual",
        "toolDescription": "Call this tool to fetch a full document page by pageNumber. This could be useful for more deep dive context."
      },
      "credentials": {
        "mongoDb": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "32dd62cd-f55b-4f43-907f-687e30b91e20",
      "name": "Combine Content & Metadata",
      "type": "n8n-nodes-base.set",
      "position": [
        3360,
        0
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "bba20778-dbf9-459b-a1aa-97a76ba01713",
              "name": "text",
              "type": "string",
              "value": "={{ $json.text }}"
            },
            {
              "id": "26d237a5-5991-4deb-867d-07b5bda6d2c2",
              "name": "metadata",
              "type": "object",
              "value": "={{\n{\n  \"pageNumber\": $json.pageNumber,\n  \"url\": $json.url\n}\n}}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "cc7eab07-bae3-4838-bdca-45db86e2c734",
      "name": "Insert Document Page",
      "type": "n8n-nodes-base.mongoDb",
      "position": [
        3536,
        0
      ],
      "parameters": {
        "fields": "text,metadata",
        "options": {},
        "operation": "insert",
        "collection": "documents"
      },
      "credentials": {
        "mongoDb": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "4d8c2a48-252a-4fe3-8ada-74bb02098347",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        3840,
        0
      ],
      "parameters": {
        "mode": "chooseBranch"
      },
      "typeVersion": 3.2
    },
    {
      "id": "c68e573f-ea44-4ed4-b60c-d27cf8d00d4d",
      "name": "Quick Update",
      "type": "@n8n/n8n-nodes-langchain.chat",
      "position": [
        1904,
        528
      ],
      "parameters": {
        "message": "={{\n(function(numResults) {\n  const replies = [\n    `Okay, I've found ${numResults} result${numResults === 1 ? '' : 's'}.`,\n    `Summarizing ${numResults} result${numResults === 1 ? '' : 's'}...`,\n    `Okay, give me a second to review these ${numResults} result${numResults === 1 ? '' : 's'}`\n  ];\n  return replies[Math.floor((Math.random() * replies.length) + 1)];\n}($json.data.length))\n}}",
        "options": {},
        "waitUserReply": false
      },
      "typeVersion": 1
    },
    {
      "id": "1fe9a7c0-40e6-4150-8741-f6fcc9532013",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -416,
        -544
      ],
      "parameters": {
        "color": 7,
        "width": 624,
        "height": 448,
        "content": "## 1. Starting Fresh\nTo begin, we'll define our document URL to process. Since we breaking down the document in full and don't want duplicate entries in our database the next time we run this ingestion step, we'll clear the our MongoDB Collection and start fresh."
      },
      "typeVersion": 1
    },
    {
      "id": "ed5cb8a7-381d-430d-a30f-15d04f60b35b",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        240,
        -544
      ],
      "parameters": {
        "color": 7,
        "width": 800,
        "height": 448,
        "content": "## 2. Download Paper and Split Into Pages\n[Read more about the HTTP node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.httprequest)\n\nA common way to extract from a PDF is to use the \"Extract from File\" node. This will return the file's metadata as well as the text split into pages - which is exactly what we need for this particular flow. Note however, if charts and images are also required to be searchable then you may need to use a vision model to properly parse these elements."
      },
      "typeVersion": 1
    },
    {
      "id": "72a31986-7c5e-4600-8c97-63e5cd92a2c1",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1072,
        -544
      ],
      "parameters": {
        "color": 7,
        "width": 832,
        "height": 448,
        "content": "## 3. For Large Documents, Use Subworkflows for Better Performance\n[Learn more about Subworkflows](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.executeworkflow)\n\nFor practical applications, smaller executions are generally preferred to help reduce out-of-memory issues in n8n. This is especially so when working with sizable documents and embedding vectors. In this particular setup, we'll process each page separately and in sequence. Though this will take longer, it can ensure our instance's stability for other workflows."
      },
      "typeVersion": 1
    },
    {
      "id": "0918ad0c-7c8e-473f-900f-194c617132c0",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1968,
        -544
      ],
      "parameters": {
        "color": 7,
        "width": 736,
        "height": 640,
        "content": "## 4. Contextual Embeddings Using Voyage-Context-3\n[Learn more about Voyage-Context-3](https://blog.voyageai.com/2025/07/23/voyage-context-3/)\n\nVoyage-Context-3 is a new contextual chunk embedding model which allows you to include document context to improve retrieval accuracy. Whereas previously you may have had to manually augment incoming chunks, Voyage-Context-3 does this automatically by allowing your to bulk upload chunks and encoding context from the aggregate of all.\n\nFor this demonstration, we won't use the full document - that's a lot of data! - but rather, we'll embed sets of 3 sequential pages. This should be enough to cover at least \"chapter\"-level context. "
      },
      "typeVersion": 1
    },
    {
      "id": "89b50026-e35d-40cb-9c16-9094d36f7ae3",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2736,
        -544
      ],
      "parameters": {
        "color": 7,
        "width": 1024,
        "height": 768,
        "content": "## 5. Store Vectors and Full Page Text for Advanced RAG Search\n[Learn about MongoDB node](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.mongodb)\n\nWe'll insert these context-aware embedding chunks into our MongoDB Atlas Vector Store along with their equivalent text content and metadata. Additionally, we can also store the full page text in Mongo as well - as we're able to later filter by page number, this can be a handy way of expanding on chunks later on in our searches."
      },
      "typeVersion": 1
    },
    {
      "id": "f7c73904-bf8a-4b7f-bd07-17e43e1bd51d",
      "name": "Insert Documents Vectors",
      "type": "n8n-nodes-base.mongoDb",
      "position": [
        3360,
        -208
      ],
      "parameters": {
        "fields": "text,embeddings,metadata",
        "options": {},
        "operation": "insert",
        "collection": "documents"
      },
      "credentials": {
        "mongoDb": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "f43c511b-b0fc-43a0-b870-dc74175469fa",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -144,
        272
      ],
      "parameters": {
        "color": 7,
        "width": 1328,
        "height": 640,
        "content": "## 6. Asking Clarifying Questions For Contextual Search\n[Read more about Respond To Chat](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-langchain.chat)\n\n**Respond to Chat** is a new Human-in-the-loop node where by the \"Human\" isn't an external source but the active user instead! This can make for really interesting multi-turn chat interactions which can feel more personalised and thus improving the user experience.\n\nFor this demonstration, we'll implement a \"clarifying questions\" loop where a set of questions are presented to the user to answer. These questions can help refine the context of the user's query and produce better search results so it's a really useful technique to know. Once the questions are answered, we can again use the \"respond to chat\" node to give a quick acknowledgement but this time with the \"wait for reply\" toggled off - this essentially becomes a \"send message\" operation."
      },
      "typeVersion": 1
    },
    {
      "id": "43848d5f-2b2c-4698-8aef-940b9b968ade",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1216,
        272
      ],
      "parameters": {
        "color": 7,
        "width": 880,
        "height": 640,
        "content": "## 2. MongoDB Atlas Vector Search Using Voyage-Context-3\n[Learn more about MongoDB $vectorSearch queries](https://www.mongodb.com/docs/atlas/atlas-vector-search/vector-search-stage/)\n\nThere's not an official MongoDB vector store node support so we'll have to write raw queries using the MongoDB node. Good thing that they're not really that hard to write once you get over the initial learning curve. Again we'll use Voyage-Context-3 on our query to match the embeddings in our vector store.\n\nOnce the documents are matched, we can use the \"respond to chat\" node to send a quick progress message to the user. These micro-updates can help break up long pauses between user questions and agent responses and provide a feeling of responsiveness.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "72773183-6b21-4726-88aa-4c5dc09fd8b6",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2128,
        272
      ],
      "parameters": {
        "color": 7,
        "width": 784,
        "height": 640,
        "content": "## 3. Q&A Agent using OpenAI GPT-4.1-Mini\n[Read more about the OpenAI node](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-langchain.openai)\n\nUsing the retrieved documents with our AI agent completes our Q&A agent flow and let's us respond to the user's query with unmatched relevancy and accuracy - or so we've been promised! Of course, you can't really tell unless you try it out for yourself.\n\nIn testing this workflow, I did find the ranking of retrieved documents to be better than naive document chunking. I could definitely recommend this contextual embeddings approach for the more demanding RAG requirements."
      },
      "typeVersion": 1
    },
    {
      "id": "ce5101b3-4ec0-4dcf-804e-1cc9f72a8b6e",
      "name": "Clear Collection",
      "type": "n8n-nodes-base.mongoDb",
      "position": [
        32,
        -336
      ],
      "parameters": {
        "query": "={ \"metadata.url\": \"{{ $json.url }}\" }",
        "operation": "delete",
        "collection": "documents"
      },
      "credentials": {
        "mongoDb": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "f9ed9fd9-d85a-43fd-b87c-4e30c9fdab72",
      "name": "For Each Group",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        2832,
        -208
      ],
      "parameters": {
        "options": {
          "reset": "={{ $('For Each Group').context.done }}"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "edb8c7d0-d909-42b9-bfd3-17e0c3c59efe",
      "name": "No Operation, do nothing",
      "type": "n8n-nodes-base.noOp",
      "position": [
        3536,
        -368
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "027cca87-9697-4923-88d4-23df75ae4d0e",
      "name": "Split Out1",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        3008,
        -208
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "data"
      },
      "typeVersion": 1
    },
    {
      "id": "5fbf397a-9054-42e0-890b-28b514e20c99",
      "name": "Aggregate1",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        3536,
        -208
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "2a706685-6ed5-4760-9127-db8608dc542d",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1184,
        -720
      ],
      "parameters": {
        "width": 608,
        "height": 944,
        "content": "## Contextual Chunk Embeddings Using Voyage-Context-3 and Mongo Atlas\n\n**On my never-ending quest to find the best embeddings model, I was intrigued to come across [Voyage-Context-3](https://blog.voyageai.com/2025/07/23/voyage-context-3/) by MongoDB and was excited to give it a try.**\n\nThis template implements the embedding model on a Arxiv research paper and stores the results in a Vector store. It was only fitting to use Mongo Atlas from the same parent company. This template also includes a RAG-based Q&A agent which taps into the vector store as a test to helps qualify if the embeddings are any good and if this is even noticeable.\n\n\n### How it works\nThis template is split into 2 parts. The first part being the import of a research document which is then chunked and embedded into our vector store. The second part builds a RAG-based Q&A agent to test the vector store retrieval on the research paper.\n\nRead the steps for more details.\n\n### How to use\n* First ensure you create a Voyage account [voyageai.com](https://voyageai.com) and a MongoDB database ready.\n* Start with Step 1 and fill in the \"Set Variables\" node and Click on the Manual Execute Trigger. This will take care of populating the vector store with the research paper.\n* To use the Q&A agent, it is required to publish the workflow to access the public chat interface. This is because \"Respond to Chat\" works best in this mode and not in editor mode.\n* To use for your own document, edit the \"Set Variables\" node to define the URL to your own document.\n* This embeddings approach should work best on larger documents.\n\n### Requirements\n* [Voyageai.com](https://voyageai.com) account for embeddings. You may need to add credit to get a reasonable RPM for this workflow.\n* MongoDB database either self-hosted or online at [https://www.mongodb.com](https://www.mongodb.com).\n* OpenAI account for RAG Q&A agent.\n\n### Need Help?\nJoin the [Discord](https://discord.com/invite/XPKeKXeB7d) or ask in the [Forum](https://community.n8n.io/)!\n\nHappy Hacking!"
      },
      "typeVersion": 1
    },
    {
      "id": "cb267ec0-1267-4968-ac5d-0bc17cd09807",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1184,
        256
      ],
      "parameters": {
        "width": 608,
        "height": 336,
        "content": "![](https://cdn.subworkflow.ai/n8n-templates/banner_595x311.png#full-width)"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Done": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait": {
      "main": [
        [
          {
            "node": "Batch 10",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "Done",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Batch 10": {
      "main": [
        [],
        [
          {
            "node": "Call Embeddings Subworkflow",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Page Ref": {
      "main": [
        [
          {
            "node": "Chunk Page Text",
            "type": "main",
            "index": 0
          },
          {
            "node": "Combine Content & Metadata",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate": {
      "main": [
        [
          {
            "node": "Quick Update",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Query": {
      "main": [
        [
          {
            "node": "Generate Clarifying Questions",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Query Ref": {
      "main": [
        [
          {
            "node": "Wait for Answer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "RAG Agent": {
      "main": [
        [
          {
            "node": "Respond to User",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out": {
      "main": [
        [
          {
            "node": "For Each Group",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate1": {
      "main": [
        [
          {
            "node": "For Each Group",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out1": {
      "main": [
        [
          {
            "node": "Combine Content & Vectors",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Pages": {
      "main": [
        [
          {
            "node": "Add Page Number",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Quick Update": {
      "main": [
        [
          {
            "node": "RAG Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Variables": {
      "main": [
        [
          {
            "node": "Clear Collection",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "For Each Group": {
      "main": [
        [
          {
            "node": "No Operation, do nothing",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Split Out1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Add Page Number": {
      "main": [
        [
          {
            "node": "Batch 10",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Chunk Page Text": {
      "main": [
        [
          {
            "node": "Voyage-Context-3 Embeddings",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [],
        [
          {
            "node": "Page Ref",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Questions": {
      "main": [
        [
          {
            "node": "Loop Over Questions",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait for Answer": {
      "main": [
        [
          {
            "node": "Loop Over Questions",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Clear Collection": {
      "main": [
        [
          {
            "node": "Import Research Paper",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Answers": {
      "main": [
        [
          {
            "node": "Quick Confirmation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract from File": {
      "main": [
        [
          {
            "node": "Split Pages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Generate Clarifying Questions",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Quick Confirmation": {
      "main": [
        [
          {
            "node": "Voyage-Context-3 Embeddings1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Questions": {
      "main": [
        [
          {
            "node": "Aggregate Answers",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Query Ref",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Subworkflow Trigger": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Insert Document Page": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Import Research Paper": {
      "main": [
        [
          {
            "node": "Extract from File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Insert Documents Vectors": {
      "main": [
        [
          {
            "node": "Aggregate1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "No Operation, do nothing": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Combine Content & Vectors": {
      "main": [
        [
          {
            "node": "Insert Documents Vectors",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Perform Similarity Search": {
      "main": [
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Combine Content & Metadata": {
      "main": [
        [
          {
            "node": "Insert Document Page",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When chat message received": {
      "main": [
        [
          {
            "node": "Get Query",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Call Embeddings Subworkflow": {
      "main": [
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Voyage-Context-3 Embeddings": {
      "main": [
        [
          {
            "node": "Split Out",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Voyage-Context-3 Embeddings1": {
      "main": [
        [
          {
            "node": "Perform Similarity Search",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Document By Page Number": {
      "ai_tool": [
        [
          {
            "node": "RAG Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Generate Clarifying Questions": {
      "main": [
        [
          {
            "node": "Split Questions",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \u2018Execute workflow\u2019": {
      "main": [
        [
          {
            "node": "Set Variables",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

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

On my never-ending quest to find the best embeddings model, I was intrigued to come across Voyage-Context-3 by MongoDB and was excited to give it a try.

Source: https://n8n.io/workflows/6819/ — 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

Code Extractfromfile. Uses manualTrigger, sort, httpRequest, compression. Event-driven trigger; 50 nodes.

HTTP Request, Compression, Edit Image +15
AI & RAG

2464. Uses httpRequest, compression, editImage, documentDefaultDataLoader. Event-driven trigger; 50 nodes.

HTTP Request, Compression, Edit Image +15
AI & RAG

Workflow 2464. Uses httpRequest, compression, editImage, documentDefaultDataLoader. Event-driven trigger; 50 nodes.

HTTP Request, Compression, Edit Image +15
AI & RAG

Are you a popular tech startup accelerator (named after a particular higher order function) overwhelmed with 1000s of pitch decks on a daily basis? Wish you could filter through them quickly using AI

HTTP Request, Compression, Edit Image +15
AI & RAG

This workflow acts as a 24/7 sales agent, engaging leads across WhatsApp, Instagram, Facebook, Telegram, and your website. It intelligently transcribes audio messages, answers questions using a knowle

Chat Trigger, Memory Postgres Chat, Tool Workflow +20