This workflow corresponds to n8n.io template #5746 — we link there as the canonical source.
This workflow follows the Form → Form 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 →
{
"id": "FKbKIlRnRWzCMkUZ",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Generate Research Ideas from PDF Documents based on Content Gaps",
"tags": [
{
"id": "66wgFoDi9Xjl74M3",
"name": "Support",
"createdAt": "2025-05-21T17:06:32.355Z",
"updatedAt": "2025-05-21T17:06:32.355Z"
},
{
"id": "kRM0hQV2zw7VxrON",
"name": "Research",
"createdAt": "2025-05-21T19:44:19.136Z",
"updatedAt": "2025-05-21T19:44:19.136Z"
},
{
"id": "sJk9cUvmMU8FkJXv",
"name": "AI",
"createdAt": "2025-05-20T13:16:15.636Z",
"updatedAt": "2025-05-20T13:16:15.636Z"
}
],
"nodes": [
{
"id": "f05941ad-6b05-4f7e-8d63-467a4f289978",
"name": "Convert File to PDF",
"type": "n8n-nodes-base.httpRequest",
"disabled": true,
"position": [
2260,
180
],
"parameters": {
"url": "https://v2.convertapi.com/convert/pdf/to/txt",
"method": "POST",
"options": {
"response": {
"response": {
"responseFormat": "text"
}
}
},
"sendBody": true,
"contentType": "multipart-form-data",
"sendHeaders": true,
"authentication": "genericCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "file",
"parameterType": "formBinaryData",
"inputDataFieldName": "data"
}
]
},
"genericAuthType": "httpBearerAuth",
"headerParameters": {
"parameters": [
{
"name": "Accept",
"value": "application/octet-stream"
}
]
}
},
"credentials": {
"httpBearerAuth": {
"name": "<your credential>"
}
},
"notesInFlow": true,
"typeVersion": 4.2
},
{
"id": "46fdd8ba-70b2-4943-8df7-958f549b65c9",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
2220,
-400
],
"parameters": {
"color": 2,
"width": 360,
"height": 820,
"content": "## Optional: Better PDF Conversion\n\n### Standard Map PDF to Text node will split your PDF files into very short chunks, which deteriorates retrieval. \n\nUse can use [ConvertAPI](https://convertapi.com?ref=4l54n) which is a high-quality convertor that will respect the layout of the original document and not cut the paragraphs into short chunks. \n\nHere is an HTTP node that makes a request to their API to convert the PDF into text. If you have a ConvertAPI account, you can replace the \"Extract Text from PDF\" node in Step 3 with this node. \n\nNote that you will need to map the text output from this node correctly in the Step 4 after.\n"
},
"typeVersion": 1
},
{
"id": "70af249f-8908-48d5-907c-0c84de4e5074",
"name": "On form submission",
"type": "n8n-nodes-base.formTrigger",
"position": [
-380,
-60
],
"parameters": {
"options": {
"appendAttribution": false
},
"formTitle": "Find Content Gaps in Your PDF Files",
"formFields": {
"values": [
{
"fieldType": "file",
"fieldLabel": "Add Your Files",
"acceptFileTypes": ".pdf"
}
]
},
"formDescription": "Upload the files you'd like to analyze and we will extract content gaps and interesting questions based on them."
},
"typeVersion": 2.2
},
{
"id": "6290cac1-3bc5-46e0-b8eb-5196a15e7ce7",
"name": "Convert binary files to PDF",
"type": "n8n-nodes-base.code",
"position": [
-60,
-60
],
"parameters": {
"jsCode": "let results = [];\n\nfor (let item of items) {\n if (item.binary) {\n // If there's binary data in the item, process each binary file\n for (let key in item.binary) {\n // Use the key as the file name\n let binaryKey = key.replace(/\\s/g, '_'); // Replace spaces with underscores for the key\n results.push({\n json: {\n fileName: binaryKey\n },\n binary: {\n [binaryKey]: item.binary[key] // Use the modified key for the binary data\n }\n });\n }\n }\n}\n\nreturn results;\n"
},
"typeVersion": 2
},
{
"id": "2c90baa0-2576-4166-819e-738f5f0c11cd",
"name": "Extract text from PDF files",
"type": "n8n-nodes-base.extractFromFile",
"position": [
280,
-60
],
"parameters": {
"options": {},
"operation": "pdf",
"binaryPropertyName": "={{ $json.fileName }}"
},
"typeVersion": 1
},
{
"id": "dbd08770-dbcd-4142-a54f-3da8beab15b5",
"name": "Prepare for InfraNodus",
"type": "n8n-nodes-base.code",
"position": [
580,
-60
],
"parameters": {
"jsCode": "\nlet plainText = '' // we send plain text from all the PDFs to InfraNodus for analysis\n\nconst randomNum = Math.floor(Math.random() * 3); // replace this with a 0 if you'd like to address the biggest gap in the knowledge graph\n\nfor (let item of items) {\n plainText += item.json.text + '\\n\\n' \n}\n\n\nreturn {text: plainText, randomNum};"
},
"typeVersion": 2
},
{
"id": "facd169e-b993-4762-a603-f167e1d0aad5",
"name": "Display on the Form to the User",
"type": "n8n-nodes-base.form",
"position": [
1840,
-40
],
"parameters": {
"operation": "completion",
"respondWith": "showText",
"responseText": "=<br>\n<h2>Question:</h2>\n<h3>{{ $('InfraNodus GraphRAG Question Generator').item.json.aiAdvice[0].text }}</h3>\n<br>\n<h2>Response:</h2>\n<h3>{{ $json.aiAdvice[0].text }}</h3>\n<br>\n"
},
"typeVersion": 1
},
{
"id": "cd16a781-fd46-4c3d-962b-1207b950f7ba",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-420,
-400
],
"parameters": {
"height": 520,
"content": "## Step 1: User uploads the PDF files for analysis\n\n### You can expose this endpoint and make it publicly available via a URL to your organization."
},
"typeVersion": 1
},
{
"id": "300eb3e7-0c37-460f-a0c1-926eb07a68c7",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-120,
-400
],
"parameters": {
"width": 280,
"height": 520,
"content": "## Step 2: Convert uploaded binaries into PDF files\n\n### We need to convert the binaries uploaded to the PDF files so we can extract text from them."
},
"typeVersion": 1
},
{
"id": "bde9366e-452a-43a7-8f78-a563bb3c23b3",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
220,
-400
],
"parameters": {
"width": 220,
"height": 520,
"content": "## Step 3: Extract plain text from PDF files\n\n### For better quality text extraction, you can use the optional [ConvertAPI](https://convertapi.com?ref=4l54n) node to the right, which respects the files' original formatting."
},
"typeVersion": 1
},
{
"id": "9e4d5981-49bf-4062-a4e2-874e43f945f8",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
520,
-400
],
"parameters": {
"width": 220,
"height": 520,
"content": "## Step 4: Combine extracted text into a text string\n\n### Prepare data for InfraNodus: combine all the extracted text into a text string and also tell InfraNodus the gap depth it should use when generating advice"
},
"typeVersion": 1
},
{
"id": "5352de5f-5d0f-4e66-8a14-a326290fbc57",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
820,
-400
],
"parameters": {
"width": 380,
"height": 820,
"content": "## Step 5: Use InfraNodus GraphRAG to build a knowledge graph, find the gap, and generate a research question based on it.\n\n### [InfraNodus](https://infranodus.com) builds a knowledge graph from all the texts, identifies the topical clusters that are least connected, and generates a research question that has a potential to bridge them in a new way.\n\n\ud83d\udea8 PROVIDE YOUR INFRANODUS API KEY HERE"
},
"typeVersion": 1
},
{
"id": "34aa69a0-2a4d-4c2c-b20a-29aa209276b6",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
1700,
-400
],
"parameters": {
"width": 380,
"height": 820,
"content": "## Step 7: Show question / prompt to the user\n\n### Optionally, you can feed the response to your other n8n workflow or expose it via a webhook and show it in your own app using an iframe."
},
"typeVersion": 1
},
{
"id": "bfad357a-e426-4bda-aa72-5df44b54be73",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
-420,
180
],
"parameters": {
"color": 5,
"width": 1160,
"height": 1000,
"content": "# How does InfraNodus GraphRAG generate research questions?\n\n## [InfraNodus](https://infranodus.com) GraphRAG helps avoid generic responses and LLM bias through analyzing your text's structure. Here's how it works:\n\n### 1. It represents your text as a network of concepts and relations building a knowledge graph.\n\n### 2. It then identifies the clusters of cocnepts that are furthest apart from each other \u2014 they appear in the same context (your texts) but are not well connected.\n\n### 3. InfraNodus will then use the AI to generate a question / prompt that bridges this gap \u2014 touching upon relevant topics but connecting them in a new way.\n\n"
},
"typeVersion": 1
},
{
"id": "d716e200-6706-4eeb-8714-34bc8a0f1229",
"name": "InfraNodus GraphRAG Question Generator",
"type": "n8n-nodes-base.httpRequest",
"position": [
960,
0
],
"parameters": {
"url": "=https://infranodus.com/api/v1/graphAndAdvice?doNotSave=true&optimize=develop&includeGraph=false&includeGraphSummary=true&gapDepth={{ $json.randomNum }}",
"method": "POST",
"options": {},
"sendBody": true,
"authentication": "genericCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "aiTopics",
"value": "true"
},
{
"name": "requestMode",
"value": "question"
},
{
"name": "text",
"value": "={{ $json.text }}"
}
]
},
"genericAuthType": "httpBearerAuth"
},
"credentials": {
"httpBearerAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "b07a00e9-9926-46e8-bc33-e1958d708f21",
"name": "InfraNodus GraphRAG Response Generator",
"type": "n8n-nodes-base.httpRequest",
"position": [
1380,
0
],
"parameters": {
"url": "=https://infranodus.com/api/v1/graphAndAdvice?doNotSave=true&optimize=imagine&includeGraph=false&includeGraphSummary=true",
"method": "POST",
"options": {},
"sendBody": true,
"authentication": "genericCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "aiTopics",
"value": "true"
},
{
"name": "requestMode",
"value": "response"
},
{
"name": "text",
"value": "={{ $('Prepare for InfraNodus').item.json.text }}"
},
{
"name": "prompt",
"value": "={{ $json.aiAdvice[0].text }}"
}
]
},
"genericAuthType": "httpBearerAuth"
},
"credentials": {
"httpBearerAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "eea5f81c-5bd8-49f3-854f-9f94992bf268",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
1240,
-400
],
"parameters": {
"width": 380,
"height": 600,
"content": "## Step 6: Generate a Response using InfraNodus GraphRAG API\n\n### Use the gap question generated by [InfraNodus](https://infranodus.com) in the previous step to generate an idea based on your PDF documents\n\n\ud83d\udea8 PROVIDE YOUR INFRANODUS API KEY HERE"
},
"typeVersion": 1
},
{
"id": "70996dc5-232d-4a3d-82e3-f36575e305bf",
"name": "Sticky Note9",
"type": "n8n-nodes-base.stickyNote",
"position": [
1240,
280
],
"parameters": {
"color": 2,
"width": 380,
"height": 900,
"content": "## Optional: Get the answers from a different collection of papers\n\n### You can use a different collection of PDFs to generate an answer, which can be especially good for cross-disciplinary research.\n\nSimply use a different set of PDFs here and add their text output to the `text` field of the InfraNodus HTTP node.\n\nYou can also use an existing InfraNodus \"expert\" graph that you save in the system to derive answers for your queries."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "c12cc761-44a5-40b0-9a17-6349f2e082d8",
"connections": {
"On form submission": {
"main": [
[
{
"node": "Convert binary files to PDF",
"type": "main",
"index": 0
}
]
]
},
"Prepare for InfraNodus": {
"main": [
[
{
"node": "InfraNodus GraphRAG Question Generator",
"type": "main",
"index": 0
}
]
]
},
"Convert binary files to PDF": {
"main": [
[
{
"node": "Extract text from PDF files",
"type": "main",
"index": 0
}
]
]
},
"Extract text from PDF files": {
"main": [
[
{
"node": "Prepare for InfraNodus",
"type": "main",
"index": 0
}
]
]
},
"InfraNodus GraphRAG Question Generator": {
"main": [
[
{
"node": "InfraNodus GraphRAG Response Generator",
"type": "main",
"index": 0
}
]
]
},
"InfraNodus GraphRAG Response Generator": {
"main": [
[
{
"node": "Display on the Form to the User",
"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.
httpBearerAuth
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This template can be used to generate research ideas from PDF scientific papers based on the content gaps found in text using the InfraNodus knowledge graph GraphRAG knowledge graph representation.
Source: https://n8n.io/workflows/5746/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow takes two inputs, YouTube video URL (required) and a description of what information to extract from the video. If the description/"what you want" field is left empty, the default prompt
Summarize YouTube Videos with Google Gemini 2.5. Uses formTrigger, httpRequest. Event-driven trigger; 10 nodes.
Deep Multiline Icebreaker automates high-quality, research-led outreach. Feed it a list of leads (emails + websites) and a short product brief via the built-in form; the workflow scrapes each company'
Submit one or more Apple Podcast episode URLs via the built-in n8n form The workflow queries the iTunes API to retrieve each podcast's public RSS feed, then parses the XML to locate the matching episo
This workflow is ideal for content creators, video marketers, and research professionals who need to extract actionable insights, detailed transcripts, or metadata from YouTube videos efficiently. It