Extract data from resume and create PDF with Gotenberg
Automate the extraction of critical information from resumes and instantly generate professional PDF summaries with this powerful n8n workflow. This solution connects Telegram, OpenAI, and Gotenberg to streamline your recruitment or data processing tasks. When a user sends a resume PDF via Telegram, the workflow triggers, extracts text using the Extract text from PDF node, and then leverages OpenAI Chat Model and specialized AI parsing nodes like Auto-fixing Output Parser and Structured Output Parser to intelligently identify and structure key data points such as personal information, education, employment history, projects, volunteering, and technologies. This structured data is then transformed into a clean HTML format using the Convert to HTML node and sent to Gotenberg via an HTTP Request to generate a polished PDF document, which is finally sent back to the user through Telegram. This workflow is ideal for recruiters, HR professionals, or anyone needing to quickly process and summarize resume data, saving significant manual effort in data entry and document creation, accelerating hiring processes, and ensuring consistent, professional output.
Workflow JSON
{"nodes": [{"id": "79849bb5-00a4-42e6-92c4-b06c7a20eb3e", "name": "OpenAI Chat Model", "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", "position": [1580, 340], "parameters": {"model": "gpt-4-turbo-preview", "options": {"temperature": 0, "responseFormat": "json_object"}}, "credentials": {"openAiApi": {"id": "", "name": "[Your openAiApi]"}}, "typeVersion": 1}, {"id": "85df0106-1f78-4412-8751-b84d417c8bf9", "name": "Convert education to HTML", "type": "n8n-nodes-base.code", "position": [2420, 180], "parameters": {"mode": "runOnceForEachItem", "jsCode": "function convertToHTML(list) {\n let html = '';\n\n list.forEach((education, index) => {\n if (index > 0) {\n html += '<br /><br />'; // Add a new line if it's not the first item\n }\n html += `<b>Institution:</b> ${education.institution}<br />\n<b>Start year:</b> ${education.start_year}<br />\n<b>Degree:</b> ${education.degree}`;\n });\n\n return html;\n}\n\n// Assuming payload is already defined\nconst payload = $input.item.json.education;\n\nconst htmlOutput = convertToHTML(payload);\nreturn {\n htmlOutput\n};"}, "typeVersion": 2}, {"id": "da4fc45d-712f-4171-b72a-66b74b4d8e05", "name": "Auto-fixing Output Parser", "type": "@n8n/n8n-nodes-langchain.outputParserAutofixing", "position": [1820, 340], "parameters": {}, "typeVersion": 1}, {"id": "225a7513-6fd4-4672-9b40-b10b00f121a7", "name": "OpenAI Chat Model1", "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", "position": [1740, 520], "parameters": {"options": {"temperature": 0}}, "credentials": {"openAiApi": {"id": "", "name": "[Your openAiApi]"}}, "typeVersion": 1}, {"id": "0606c99d-a080-4277-b071-1bc0c93bb2e3", "name": "Structured Output Parser", "type": "@n8n/n8n-nodes-langchain.outputParserStructured", "position": [1960, 520], "parameters": {"jsonSchema": "{\n \"type\": \"object\",\n \"properties\": {\n \"personal_info\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": { \"type\": \"string\" },\n \"address\": { \"type\": \"string\" },\n \"email\": { \"type\": \"string\", \"format\": \"email\" },\n \"github\": { \"type\": \"string\"},\n \"linkedin\": { \"type\": \"string\" }\n }\n },\n \"employment_history\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"position\": { \"type\": \"string\" },\n \"company\": { \"type\": \"string\" },\n \"duration\": { \"type\": \"string\" },\n \"responsibilities\": {\n \"type\": \"array\",\n \"items\": { \"type\": \"string\" }\n }\n }\n }\n },\n \"education\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"institution\": { \"type\": \"string\" },\n \"start_year\": { \"type\": \"integer\" },\n \"degree\": { \"type\": \"string\" }\n }\n }\n },\n \"projects\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": { \"type\": \"string\" },\n \"year\": { \"type\": \"integer\" },\n \"description\": { \"type\": \"string\" },\n \"technologies\": {\n \"type\": \"array\",\n \"items\": { \"type\": \"string\" }\n }\n }\n }\n },\n \"volunteering\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"activity\": { \"type\": \"string\" },\n \"location\": { \"type\": \"string\" },\n \"date\": { \"type\": \"string\" },\n \"description\": { \"type\": \"string\" }\n }\n }\n },\n \"programming_languages\": {\n \"type\": \"object\",\n \"properties\": {\n \"languages\": {\n \"type\": \"array\",\n \"items\": { \"type\": \"string\" }\n },\n \"tools\": {\n \"type\": \"array\",\n \"items\": { \"type\": \"string\" }\n },\n \"methodologies\": {\n \"type\": \"array\",\n \"items\": { \"type\": \"string\" }\n }\n }\n },\n \"foreign_languages\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"language\": { \"type\": \"string\" },\n \"level\": { \"type\": \"string\" }\n }\n }\n }\n }\n}\n"}, "typeVersion": 1}, {"id": "027975cd-768a-4048-858d-9060f48ab622", "name": "Convert employment history to HTML", "type": "n8n-nodes-base.code", "position": [2420, -20], "parameters": {"mode": "runOnceForEachItem", "jsCode": "function convertToHTML(list) {\n let html = '';\n\n list.forEach((item, index) => {\n if (index > 0) {\n html += '<br />'; // Add a new line if it's not the first item\n }\n html += `<b>Position:</b> ${item.position}\n<b>Company:</b> ${item.company}\n<br />\n<b>Duration:</b> ${item.duration}\n<br />\n<b>Responsibilities:</b>\n`;\n\n item.responsibilities.forEach((responsibility, i) => {\n html += `- ${responsibility}`;\n if (i < item.responsibilities.length - 1 || index < list.length - 1) {\n html += '<br />'; // Add new line if it's not the last responsibility in the last item\n }\n });\n });\n\n return html;\n}\n\n// Assuming payload is already defined\nconst payload = $input.item.json.employment_history;\n\nconst htmlOutput = convertToHTML(payload);\nreturn {\n htmlOutput\n};"}, "typeVersion": 2}, {"id": "823a241d-1c68-40a9-8f2c-f1bdfaab7603", "name": "Convert projects to HTML", "type": "n8n-nodes-base.code", "position": [2420, 380], "parameters": {"mode": "runOnceForEachItem", "jsCode": "function convertToHTML(list) {\n let html = '';\n\n list.forEach((project, index) => {\n if (index > 0) {\n html += '<br />'; // Add a new line if it's not the first project\n }\n html += `<b>Name:</b> ${project.name}<br />\n<b>Year:</b> ${project.year}<br />\n<b>Description:</b> ${project.description}<br /><br />\n<b>Technologies:</b>\n<br />`;\n\n project.technologies.forEach((technology, i) => {\n html += `- ${technology}`;\n if (i < project.technologies.length - 1 || index < list.length - 1) {\n html += '<br />'; // Add new line if it's not the last technology in the last project\n }\n });\n });\n\n return html;\n}\n\n// Assuming payload is already defined\nconst payload = $input.item.json.projects;\n\nconst htmlOutput = convertToHTML(payload);\nreturn {\n htmlOutput\n};\n"}, "typeVersion": 2}, {"id": "a12eb0e1-1cb9-4b83-a1ec-42dd8214f6bc", "name": "Convert volunteering to HTML", "type": "n8n-nodes-base.code", "position": [2420, 580], "parameters": {"mode": "runOnceForEachItem", "jsCode": "function convertToHTML(list) {\n let html = '';\n\n list.forEach((event, index) => {\n if (index > 0) {\n html += '<br />'; // Add a new line if it's not the first volunteering event\n }\n html += `<b>Activity:</b> ${event.activity}<br />\n<b>Location:</b> ${event.location}<br />\n<b>Date:</b> ${event.date}<br />\n<b>Description:</b> ${event.description}<br />`;\n });\n\n return html;\n}\n\n// Assuming payload is already defined\nconst payload = $input.item.json.volunteering;\n\nconst htmlOutput = convertToHTML(payload);\nreturn {\n htmlOutput\n};\n"}, "typeVersion": 2}, {"id": "70b67b80-d22d-4eea-8c97-3d2cb2b9bbfc", "name": "Telegram trigger", "type": "n8n-nodes-base.telegramTrigger", "position": [360, 340], "webhookId": "d6829a55-a01b-44ac-bad3-2349324c8515", "parameters": {"updates": ["message"], "additionalFields": {}}, "credentials": {"telegramApi": {"id": "", "name": "[Your telegramApi]"}}, "typeVersion": 1.1}, {"id": "21bead1d-0665-44d5-b623-b0403c9abd6c", "name": "Auth", "type": "n8n-nodes-base.if", "position": [600, 340], "parameters": {"options": {}, "conditions": {"options": {"leftValue": "", "caseSensitive": true, "typeValidation": "strict"}, "combinator": "and", "conditions": [{"id": "7ca4b4c3-e23b-4896-a823-efc85c419467", "operator": {"type": "number", "operation": "equals"}, "leftValue": "={{ $json.message.chat.id }}", "rightValue": 0}]}}, "typeVersion": 2}, {"id": "de76d6ec-3b0e-44e0-943d-55547aac2e46", "name": "No operation (unauthorized)", "type": "n8n-nodes-base.noOp", "position": [860, 520], "parameters": {}, "typeVersion": 1}, {"id": "439f5e2c-be7d-486b-a1f1-13b09f77c2c8", "name": "Check if start message", "type": "n8n-nodes-base.if", "position": [860, 220], "parameters": {"options": {}, "conditions": {"options": {"leftValue": "", "caseSensitive": true, "typeValidation": "strict"}, "combinator": "and", "conditions": [{"id": "1031f14f-9793-488d-bb6b-a021f943a399", "operator": {"type": "string", "operation": "notEquals"}, "leftValue": "={{ $json.message.text }}", "rightValue": "/start"}]}}, "typeVersion": 2}, {"id": "af5f5622-c338-40c0-af72-90e124ed7ce1", "name": "No operation (start message)", "type": "n8n-nodes-base.noOp", "position": [1120, 360], "parameters": {}, "typeVersion": 1}, {"id": "2efae11a-376b-44aa-ab91-9b3dea82ede0", "name": "Get file", "type": "n8n-nodes-base.telegram", "position": [1120, 120], "parameters": {"fileId": "={{ $json.message.document.file_id }}", "resource": "file"}, "credentials": {"telegramApi": {"id": "", "name": "[Your telegramApi]"}}, "typeVersion": 1.1}, {"id": "88fd1002-ad2c-445f-92d4-11b571db3788", "name": "Extract text from PDF", "type": "n8n-nodes-base.extractFromFile", "position": [1380, 120], "parameters": {"options": {}, "operation": "pdf"}, "typeVersion": 1}, {"id": "9dfc204b-c567-418a-93a3-9b72cf534a8c", "name": "Set parsed fileds", "type": "n8n-nodes-base.set", "position": [2040, 120], "parameters": {"options": {}}, "typeVersion": 3.2}, {"id": "314c771a-5ff2-484f-823b-0eab88f43ea3", "name": "Personal info", "type": "n8n-nodes-base.set", "position": [2420, -380], "parameters": {"fields": {"values": [{"name": "personal_info", "stringValue": "=<b><u>Personal info</u></b>\n<br /><br />\n<b>Name:</b> {{ $json.personal_info.name }}\n<br />\n<b>Address:</b> {{ $json.personal_info.address }}\n<br />\n<b>Email:</b> {{ $json.personal_info.email }}\n<br />\n<b>GitHub:</b> {{ $json.personal_info.github }}\n<br />"}]}, "include": "none", "options": {}}, "typeVersion": 3.2}, {"id": "be6b32e8-6000-4235-a723-0e22828ead45", "name": "Technologies", "type": "n8n-nodes-base.set", "position": [2420, -200], "parameters": {"fields": {"values": [{"name": "technologies", "stringValue": "=<b><u>Technologies</u></b>\n<br /><br />\n<b>Programming languages:</b> {{ $json.programming_languages.languages.join(', ') }}\n<br />\n<b>Tools:</b> {{ $json.programming_languages.tools.join(', ') }}\n<br />\n<b>Methodologies:</b> {{ $json.programming_languages.methodologies.join(', ') }}\n<br />"}]}, "include": "none", "options": {}}, "typeVersion": 3.2}, {"id": "ab726d61-84b8-4af7-a195-33e1add89153", "name": "Employment history", "type": "n8n-nodes-base.set", "position": [2640, -20], "parameters": {"fields": {"values": [{"name": "employment_history", "stringValue": "=<b><u>Employment history</u></b>\n<br /><br />\n{{ $json[\"htmlOutput\"] }}"}]}, "include": "none", "options": {}}, "typeVersion": 3.2}, {"id": "692f9555-6102-4d3c-b0a1-868e27e3c343", "name": "Education", "type": "n8n-nodes-base.set", "position": [2640, 180], "parameters": {"fields": {"values": [{"name": "education", "stringValue": "=<b><u>Education</u></b>\n<br /><br />\n{{ $json[\"htmlOutput\"] }}"}]}, "include": "none", "options": {}}, "typeVersion": 3.2}, {"id": "258728f2-1f03-4786-8197-feb9f1bc4dfe", "name": "Projects", "type": "n8n-nodes-base.set", "position": [2640, 380], "parameters": {"fields": {"values": [{"name": "projects", "stringValue": "=<b><u>Projects</u></b>\n<br /><br />\n{{ $json[\"htmlOutput\"] }}"}]}, "include": "none", "options": {}}, "typeVersion": 3.2}, {"id": "3c819ce4-235a-4b12-a396-d33dca9f80da", "name": "Volunteering", "type": "n8n-nodes-base.set", "position": [2640, 580], "parameters": {"fields": {"values": [{"name": "volunteering", "stringValue": "=<b><u>Volunteering</u></b>\n<br /><br />\n{{ $json[\"htmlOutput\"] }}"}]}, "include": "none", "options": {}}, "typeVersion": 3.2}, {"id": "41bd7506-7330-4c25-8b43-aa3c836736fc", "name": "Merge education and employment history", "type": "n8n-nodes-base.merge", "position": [2880, 100], "parameters": {"mode": "combine", "options": {}, "combinationMode": "multiplex"}, "typeVersion": 2.1}, {"id": "d788da36-360b-4009-82ad-2f206fad8e53", "name": "Merge projects and volunteering", "type": "n8n-nodes-base.merge", "position": [2880, 500], "parameters": {"mode": "combine", "options": {}, "combinationMode": "multiplex"}, "typeVersion": 2.1}, {"id": "57c20e19-3d84-41c0-a415-1d55cb031da1", "name": "Merge personal info and technologies", "type": "n8n-nodes-base.merge", "position": [3140, -160], "parameters": {"mode": "combine", "options": {}, "combinationMode": "multiplex"}, "typeVersion": 2.1}, {"id": "f12be010-8375-4ff7-ba8e-9c2c870f648b", "name": "Merge all", "type": "n8n-nodes-base.merge", "position": [3400, 200], "parameters": {"mode": "combine", "options": {}, "combinationMode": "multiplex"}, "typeVersion": 2.1}, {"id": "d6428167-2c75-42a5-a905-7590ff1d6a25", "name": "Set final data", "type": "n8n-nodes-base.set", "position": [3620, 200], "parameters": {"fields": {"values": [{"name": "output", "stringValue": "={{ $json.personal_info }}\n<br /><br />\n{{ $json.employment_history }}\n<br /><br />\n{{ $json.education }}\n<br /><br />\n{{ $json.projects }}\n<br /><br />\n{{ $json.volunteering }}\n<br /><br />\n{{ $json.technologies }}"}]}, "include": "none", "options": {}}, "typeVersion": 3.2}, {"id": "9ea13c62-2e09-4b37-b889-66edaef1fcf1", "name": "Convert raw to base64", "type": "n8n-nodes-base.code", "position": [3840, 200], "parameters": {"mode": "runOnceForEachItem", "jsCode": "const encoded = Buffer.from($json.output).toString('base64');\n\nreturn { encoded };"}, "typeVersion": 2}, {"id": "c4474fa1-b1b5-432f-b30e-100201c9ec7c", "name": "Convert to HTML", "type": "n8n-nodes-base.convertToFile", "position": [4060, 200], "parameters": {"options": {"fileName": "index.html", "mimeType": "text/html"}, "operation": "toBinary", "sourceProperty": "encoded"}, "typeVersion": 1.1}, {"id": "3c4d2010-1bdc-4f01-bb1a-bd0128017787", "name": "Generate plain PDF doc", "type": "n8n-nodes-base.httpRequest", "position": [4340, 200], "parameters": {"url": "http://gotenberg:3000/forms/chromium/convert/html", "method": "POST", "options": {"response": {"response": {"responseFormat": "file"}}}, "sendBody": true, "contentType": "multipart-form-data", "bodyParameters": {"parameters": [{"name": "files", "parameterType": "formBinaryData", "inputDataFieldName": "data"}]}}, "typeVersion": 4.1}, {"id": "2b3cd55f-21a3-4c14-905f-82b158aa3fd0", "name": "Send PDF to the user", "type": "n8n-nodes-base.telegram", "position": [4640, 200], "parameters": {"chatId": "={{ $('Telegram trigger').item.json[\"message\"][\"chat\"][\"id\"] }}", "operation": "sendDocument", "binaryData": true, "additionalFields": {"fileName": "={{ $('Set parsed fileds').item.json[\"personal_info\"][\"name\"].toLowerCase().replace(' ', '-') }}.pdf"}}, "credentials": {"telegramApi": {"id": "", "name": "[Your telegramApi]"}}, "typeVersion": 1.1}, {"id": "54fe1d2d-eb9d-4fe1-883f-1826e27ac873", "name": "Sticky Note", "type": "n8n-nodes-base.stickyNote", "position": [540, 180], "parameters": {"width": 226.21234567901217, "height": 312.917333333334, "content": "### Add chat ID\nRemember to set your actual ID to trigger automation from Telegram."}, "typeVersion": 1}, {"id": "b193a904-260b-4d45-8a66-e3cb46fc7ce4", "name": "Sticky Note1", "type": "n8n-nodes-base.stickyNote", "position": [800, 83.43940740740783], "parameters": {"width": 229.64938271604922, "height": 293.54824691358016, "content": "### Ignore start message\nWorkflow ignores initial`/start` message sent to the bot."}, "typeVersion": 1}, {"id": "d5c95d8f-b699-4a8e-9460-a4f5856b5e6f", "name": "Sticky Note2", "type": "n8n-nodes-base.stickyNote", "position": [1066, -20], "parameters": {"width": 211.00246913580224, "height": 302.41975308642, "content": "### Download resume file\nBased on file ID, node performs downloading of the file uploaded by user."}, "typeVersion": 1}, {"id": "2de0751d-8e11-457e-8c38-a6dcca59190c", "name": "Sticky Note4", "type": "n8n-nodes-base.stickyNote", "position": [1320, -20], "parameters": {"width": 217.87654320987633, "height": 302.41975308642, "content": "### Extract text from PDF\nNode extracts readable text form PDF."}, "typeVersion": 1}, {"id": "4b9ccab8-ff6c-408f-93fe-f148034860a0", "name": "Sticky Note5", "type": "n8n-nodes-base.stickyNote", "position": [1580, -20], "parameters": {"width": 410.9479506172837, "height": 302.41975308642, "content": "### Parse resume data\nCreate structured data from text extracted from resume. Chain uses OpenAI `gpt-4-turbo-preview` model and JSON response mode. **Adjust JSON schema in output parser to your needs.**"}, "typeVersion": 1}, {"id": "bfb1d382-90fa-4bff-8c38-04e53bcf5f58", "name": "Parse resume data", "type": "@n8n/n8n-nodes-langchain.chainLlm", "position": [1660, 120], "parameters": {"prompt": "={{ $json.text }}", "messages": {"messageValues": [{"message": "Your task is to extract all necessary data such as first name, last name, experience, known technologies etc. from the provided resume text and return in well-unified JSON format. Do not make things up."}]}}, "typeVersion": 1.3}, {"id": "7e8eb10a-f21c-4a9c-90b1-b71537b78356", "name": "Merge other data", "type": "n8n-nodes-base.merge", "position": [3140, 340], "parameters": {"mode": "combine", "options": {}, "combinationMode": "multiplex"}, "typeVersion": 2.1}, {"id": "7c4398de-7b4d-4095-b38f-eaf099d2991b", "name": "Sticky Note6", "type": "n8n-nodes-base.stickyNote", "position": [2340, -491.4074074074074], "parameters": {"width": 1196.8442469135782, "height": 1260.345679012346, "content": "### Format HTML\nFormat HTML for each resume section (employment history, projects etc.)."}, "typeVersion": 1}, {"id": "9de2f504-6ff0-4b00-8e0d-436c789b4e23", "name": "Sticky Note7", "type": "n8n-nodes-base.stickyNote", "position": [3580, 40], "parameters": {"width": 638.6516543209876, "height": 322.5837037037037, "content": "### Create HTML file\nFrom formatted output create `index.html` file in order to run PDF conversion."}, "typeVersion": 1}, {"id": "11abdff5-377e-490d-9136-15c24ff6a05e", "name": "Sticky Note8", "type": "n8n-nodes-base.stickyNote", "position": [4260, 39.83604938271645], "parameters": {"color": 3, "width": 262.0096790123454, "height": 322.5837037037035, "content": "### Convert file to PDF\nForm `index.html` create PDF using [Gotenberg](https://gotenberg.dev/). If you're not familiar with this software, feel free to check out [my tutorial on YouTube](https://youtu.be/bo15xdjXf1Y?si=hFZMTfjzfSOLOLPK)."}, "typeVersion": 1}, {"id": "73fb81d0-5218-4311-aaec-7fa259d8cbd3", "name": "Sticky Note9", "type": "n8n-nodes-base.stickyNote", "position": [4560, 40], "parameters": {"width": 262.0096790123454, "height": 322.5837037037035, "content": "### Send PDF file to user\nDeliver converted PDF to Telegram user (based on chat ID)."}, "typeVersion": 1}, {"id": "bb5fa375-4cc9-4559-a014-7b618d6c5f32", "name": "Sticky Note10", "type": "n8n-nodes-base.stickyNote", "position": [-280, 128], "parameters": {"width": 432.69769500990674, "height": 364.2150828344463, "content": "## \u26a0\ufe0f Note\n\nThis is *resume extractor* workflow that I had a pleasure to present during [n8n community hangout](https://youtu.be/eZacuxrhCuo?si=KkJQrgQuvLxj-6FM&t=1701\n) on March 7, 2024.\n\n1. Remember to add your credentials and configure nodes.\n2. This node requires installed [Gotenberg](https://gotenberg.dev/) for PDF generation. If you're not familiar with this software, feel free to check out [my tutorial on YouTube](https://youtu.be/bo15xdjXf1Y?si=hFZMTfjzfSOLOLPK). If you don't want to self-host Gotenberg, you use other PDF generation provider (PDFMonkey, ApiTemplate or similar).\n3. If you like this workflow, please subscribe to [my YouTube channel](https://www.youtube.com/@workfloows) and/or [my newsletter](https://workfloows.com/).\n\n**Thank you for your support!**"}, "typeVersion": 1}], "connections": {"Auth": {"main": [[{"node": "Check if start message", "type": "main", "index": 0}], [{"node": "No operation (unauthorized)", "type": "main", "index": 0}]]}, "Get file": {"main": [[{"node": "Extract text from PDF", "type": "main", "index": 0}]]}, "Projects": {"main": [[{"node": "Merge projects and volunteering", "type": "main", "index": 0}]]}, "Education": {"main": [[{"node": "Merge education and employment history", "type": "main", "index": 1}]]}, "Merge all": {"main": [[{"node": "Set final data", "type": "main", "index": 0}]]}, "Technologies": {"main": [[{"node": "Merge personal info and technologies", "type": "main", "index": 1}]]}, "Volunteering": {"main": [[{"node": "Merge projects and volunteering", "type": "main", "index": 1}]]}, "Personal info": {"main": [[{"node": "Merge personal info and technologies", "type": "main", "index": 0}]]}, "Set final data": {"main": [[{"node": "Convert raw to base64", "type": "main", "index": 0}]]}, "Convert to HTML": {"main": [[{"node": "Generate plain PDF doc", "type": "main", "index": 0}]]}, "Merge other data": {"main": [[{"node": "Merge all", "type": "main", "index": 1}]]}, "Telegram trigger": {"main": [[{"node": "Auth", "type": "main", "index": 0}]]}, "OpenAI Chat Model": {"ai_languageModel": [[{"node": "Parse resume data", "type": "ai_languageModel", "index": 0}]]}, "Parse resume data": {"main": [[{"node": "Set parsed fileds", "type": "main", "index": 0}]]}, "Set parsed fileds": {"main": [[{"node": "Convert employment history to HTML", "type": "main", "index": 0}, {"node": "Convert education to HTML", "type": "main", "index": 0}, {"node": "Convert projects to HTML", "type": "main", "index": 0}, {"node": "Personal info", "type": "main", "index": 0}, {"node": "Convert volunteering to HTML", "type": "main", "index": 0}, {"node": "Technologies", "type": "main", "index": 0}]]}, "Employment history": {"main": [[{"node": "Merge education and employment history", "type": "main", "index": 0}]]}, "OpenAI Chat Model1": {"ai_languageModel": [[{"node": "Auto-fixing Output Parser", "type": "ai_languageModel", "index": 0}]]}, "Convert raw to base64": {"main": [[{"node": "Convert to HTML", "type": "main", "index": 0}]]}, "Extract text from PDF": {"main": [[{"node": "Parse resume data", "type": "main", "index": 0}]]}, "Check if start message": {"main": [[{"node": "Get file", "type": "main", "index": 0}], [{"node": "No operation (start message)", "type": "main", "index": 0}]]}, "Generate plain PDF doc": {"main": [[{"node": "Send PDF to the user", "type": "main", "index": 0}]]}, "Convert projects to HTML": {"main": [[{"node": "Projects", "type": "main", "index": 0}]]}, "Structured Output Parser": {"ai_outputParser": [[{"node": "Auto-fixing Output Parser", "type": "ai_outputParser", "index": 0}]]}, "Auto-fixing Output Parser": {"ai_outputParser": [[{"node": "Parse resume data", "type": "ai_outputParser", "index": 0}]]}, "Convert education to HTML": {"main": [[{"node": "Education", "type": "main", "index": 0}]]}, "Convert volunteering to HTML": {"main": [[{"node": "Volunteering", "type": "main", "index": 0}]]}, "Merge projects and volunteering": {"main": [[{"node": "Merge other data", "type": "main", "index": 1}]]}, "Convert employment history to HTML": {"main": [[{"node": "Employment history", "type": "main", "index": 0}]]}, "Merge personal info and technologies": {"main": [[{"node": "Merge all", "type": "main", "index": 0}]]}, "Merge education and employment history": {"main": [[{"node": "Merge other data", "type": "main", "index": 0}]]}}}How to Import This Workflow
- 1Copy the workflow JSON above using the Copy Workflow JSON button.
- 2Open your n8n instance and go to Workflows.
- 3Click Import from JSON and paste the copied workflow.
Don't have an n8n instance? Start your free trial at n8nautomation.cloud
Related Templates
Ask questions about a PDF using AI
Effortlessly transform your Google Drive PDFs into an interactive knowledge base with this powerful AI workflow. This n8n automation connects your Google Drive files, processes them with OpenAI embeddings, and stores them in a Pinecone vector database, allowing you to ask questions and receive intelligent answers directly from your document content. When a new PDF is uploaded to Google Drive, the workflow automatically extracts its text, splits it into manageable chunks using the Recursive Character Text Splitter, generates embeddings via OpenAI, and then inserts this structured data into Pinecone for efficient retrieval. Later, by clicking the 'Chat' button, you can engage in a natural language conversation with your document, powered by the OpenAI Chat Model and the Question and Answer Chain, which retrieves relevant information from Pinecone. This is ideal for researchers needing to quickly extract insights from large reports, legal professionals analyzing contracts, or businesses creating searchable knowledge bases from their documentation, saving countless hours of manual review and information searching.
Supabase Insertion & Upsertion & Retrieval
Efficiently manage and query your data with the Supabase Insertion & Upsertion & Retrieval workflow, a powerful solution for integrating document management with intelligent data processing. This 21-node workflow, triggered manually, connects Google Drive, Supabase, and OpenAI to automate the ingestion, updating, and retrieval of information. It allows you to upload documents from Google Drive, which are then processed by a Recursive Character Text Splitter and embedded using OpenAI Embeddings for insertion or upsertion into your Supabase vector store via the Insert Documents and Update Documents nodes. When a chat message is received, the workflow leverages OpenAI's Chat Model and a Question and Answer Chain to retrieve relevant information from Supabase using the Retrieve by Query node, providing intelligent responses based on your stored documents. This workflow is ideal for businesses and individuals who need to maintain an up-to-date knowledge base, power AI-driven chatbots with proprietary information, or automate the synchronization of document content with a searchable database, significantly reducing manual data entry and improving information accessibility.
Chat with Postgresql Database
Empower your users to interact with your PostgreSQL database using natural language by automating the process of querying and retrieving information. This workflow connects a chat interface, triggered by a new message, to an AI Agent that leverages OpenAI's powerful language model to understand user requests. The AI Agent intelligently utilizes a suite of PostgreSQL tools, including "Get Table Definition," "Execute SQL Query," and "Get DB Schema and Tables List," to dynamically fetch database schema, generate appropriate SQL queries, and execute them against your database. Chat history is maintained using an AI memory buffer, allowing for contextual conversations. This solution is ideal for support teams needing quick data lookups, business analysts exploring data without writing SQL, or developers building interactive data dashboards. It eliminates the need for manual SQL query writing, speeds up data access, and reduces the training burden for non-technical users, saving significant time and resources while improving data accessibility.