This workflow follows the Chainllm → Google Drive 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 →
{
"name": "rag_faq_extractor",
"nodes": [
{
"parameters": {},
"id": "b7e8c306-95d7-493a-9594-0b0549e93eeb",
"name": "Manual Trigger",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
-1440,
80
]
},
{
"parameters": {
"model": "mistral-large-latest",
"options": {}
},
"id": "656b9cbe-b346-479f-8a27-dde776a95391",
"name": "Mistral Chat Model 1",
"type": "@n8n/n8n-nodes-langchain.lmChatMistralCloud",
"typeVersion": 1,
"position": [
-1008,
272
],
"credentials": {
"mistralCloudApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"model": "mistral-large-latest",
"options": {}
},
"id": "7361d2aa-9ee4-430a-89c1-9cbfef84d0d6",
"name": "Mistral Chat Model 2",
"type": "@n8n/n8n-nodes-langchain.lmChatMistralCloud",
"typeVersion": 1,
"position": [
-272,
288
],
"credentials": {
"mistralCloudApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"model": "mistral-large-latest",
"options": {}
},
"id": "e1dc4ace-daa6-48a1-ab51-2ee4aa65e6f5",
"name": "Mistral Chat Model 3",
"type": "@n8n/n8n-nodes-langchain.lmChatMistralCloud",
"typeVersion": 1,
"position": [
608,
-48
],
"credentials": {
"mistralCloudApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"inputDataFieldName": "json_output",
"name": "faq.json",
"driveId": {
"__rl": true,
"value": "My Drive",
"mode": "list",
"cachedResultName": "My Drive",
"cachedResultUrl": "https://drive.google.com/drive/my-drive"
},
"folderId": {
"__rl": true,
"value": "root",
"mode": "list",
"cachedResultName": "/ (Root folder)",
"cachedResultUrl": "https://drive.google.com/drive"
},
"options": {}
},
"type": "n8n-nodes-base.googleDrive",
"typeVersion": 3,
"position": [
1808,
-240
],
"id": "2eeeb088-b51f-4ffa-ac9e-4e0d457f0ed4",
"name": "Upload file",
"credentials": {
"googleDriveOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"url": "https://r.jina.ai/https://faq.tagheuer.com/?l=fr&c=Products:All_TAG_Heuer_Connected",
"options": {}
},
"id": "38daefdb-59e1-4276-83c9-f778af33a18f",
"name": "Get FAQ first page",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-1216,
80
]
},
{
"parameters": {
"promptType": "define",
"text": "=Analyse ce contenu markdown d'une page FAQ et extrait UNIQUEMENT les URLs des sous-cat\u00e9gories de la section Connected et ajoute aussi l'url : https://faq.tagheuer.com/?l=fr&c=Products:All_TAG_Heuer_Connected.\n\nContenu:\n{{ $json.data }}\n\nRetourne un JSON array avec les URLs compl\u00e8tes des sous-cat\u00e9gories. Format attendu:\n{\n \"subcategories\": [\n \"https://faq.tagheuer.com/?l=fr&c=Products:Connected:Subcategory1\",\n \"https://faq.tagheuer.com/?l=fr&c=Products:Connected:Subcategory2\"\n ]\n}\n\nRetourne UNIQUEMENT le JSON, rien d'autre."
},
"id": "9b7ebca8-e46e-4dd0-89c5-b718e3b83d21",
"name": "Extract categories",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"typeVersion": 1.4,
"position": [
-1008,
80
]
},
{
"parameters": {
"jsCode": "// R\u00e9cup\u00e9rer la r\u00e9ponse du LLM\nconst input = $input.first().json;\nlet response = input.output || input.text || input.response || JSON.stringify(input);\n\nconsole.log('R\u00e9ponse brute du LLM:', response);\n\nlet parsed;\n\ntry {\n // Si la r\u00e9ponse est d\u00e9j\u00e0 un objet\n if (typeof response === 'object') {\n parsed = response;\n } else {\n // Nettoyer la r\u00e9ponse (enlever markdown, backticks, etc.)\n response = response.replace(/```json\\n?/g, '').replace(/```\\n?/g, '').trim();\n \n // Extraire le JSON de la r\u00e9ponse\n const jsonMatch = response.match(/\\{[\\s\\S]*\\}/);\n if (jsonMatch) {\n parsed = JSON.parse(jsonMatch[0]);\n } else {\n parsed = JSON.parse(response);\n }\n }\n} catch (e) {\n console.error('Erreur de parsing:', e.message);\n console.error('R\u00e9ponse qui a caus\u00e9 l\\'erreur:', response);\n return [{ error: 'Parsing failed', rawResponse: response }];\n}\n\nconsole.log('JSON pars\u00e9:', parsed);\n\nconst urls = parsed.subcategories || [];\n\nif (urls.length === 0) {\n console.warn('Aucune sous-cat\u00e9gorie trouv\u00e9e');\n return [{ warning: 'No subcategories found', parsed: parsed }];\n}\n\nreturn urls.map(url => ({ url: url }));"
},
"id": "f86956ae-a0bc-40dc-860f-908107b0034a",
"name": "Parser categories",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-688,
80
]
},
{
"parameters": {
"url": "=https://r.jina.ai/{{ $json.url }}",
"options": {}
},
"id": "884ea90d-9e69-42c2-85e8-89c805977aa2",
"name": "Get questions / answers url by category",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-464,
80
]
},
{
"parameters": {
"promptType": "define",
"text": "=Analyse ce contenu markdown d'une page FAQ et extrait TOUTES les questions avec leurs liens vers les r\u00e9ponses.\n\nContenu:\n{{ $json.data }}\n\nRetourne un JSON array avec les questions et URLs. Format attendu:\n{\n \"questions\": [\n {\n \"question\": \"Texte de la question\",\n \"url\": \"https://faq.tagheuer.com/...\"\n }\n ]\n}\n\nRetourne UNIQUEMENT le JSON, rien d'autre."
},
"id": "20e8df4b-f238-4f8a-951b-d01d32e2b1ff",
"name": "Extract questions / answers",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"typeVersion": 1.4,
"position": [
-272,
80
]
},
{
"parameters": {
"language": "pythonNative",
"pythonCode": "import json\nimport re\n\nresults = []\n\nfor item in _items:\n response = item[\"json\"][\"text\"]\n\n response = re.sub(r'```json\\n?', '', response, flags=re.IGNORECASE)\n response = re.sub(r'```\\n?', '', response).strip()\n\n results.extend(json.loads(response)[\"questions\"])\n\nreturn results\n"
},
"id": "a1ff0f1e-8060-49ab-9183-d9584dd7cbfa",
"name": "Parser questions / answers",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
80,
80
]
},
{
"parameters": {
"url": "=https://r.jina.ai/{{ $('Loop Over Questions').item.json.url }}",
"options": {}
},
"id": "53b629bc-f4e9-4305-984e-cf7ce31fe9be",
"name": "Get answer",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1184,
112
]
},
{
"parameters": {
"options": {}
},
"type": "n8n-nodes-base.splitInBatches",
"typeVersion": 3,
"position": [
336,
80
],
"id": "86854aa5-cb4f-488e-9b99-8de90ddf7bbe",
"name": "Loop Over Questions"
},
{
"parameters": {
"amount": 10
},
"type": "n8n-nodes-base.wait",
"typeVersion": 1.1,
"position": [
960,
112
],
"id": "db4ea897-23f1-4221-b0f0-70c578046da8",
"name": "Wait"
},
{
"parameters": {
"promptType": "define",
"text": "=Extrait la r\u00e9ponse compl\u00e8te de cette page FAQ.\n\nContenu:\n{{ $json.data }}\n\nRetourne un JSON avec la r\u00e9ponse. Format attendu:\n{\n \"answer\": \"Texte complet de la r\u00e9ponse\"\n}\n\nRetourne UNIQUEMENT le JSON, rien d'autre."
},
"id": "7574e42f-f75f-44bd-a634-4e264d5f4f32",
"name": "Extract answer",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"typeVersion": 1.4,
"position": [
608,
-256
]
},
{
"parameters": {
"language": "pythonNative",
"pythonCode": "import json\nimport re\n\nresults = []\n\nfor item in _items:\n response = item[\"json\"][\"text\"]\n\n response = re.sub(r'```json\\n?', '', response, flags=re.IGNORECASE)\n response = re.sub(r'```\\n?', '', response).strip()\n\n results.append(json.loads(response))\n\nreturn results"
},
"id": "e55b2a2b-244e-40b8-aedc-1eac9130348e",
"name": "Parse answer",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
928,
-256
]
},
{
"parameters": {
"mode": "combine",
"combineBy": "combineByPosition",
"options": {}
},
"type": "n8n-nodes-base.merge",
"typeVersion": 3.2,
"position": [
1184,
-240
],
"id": "04110840-9a2f-4e71-8ed9-4a850f744cf9",
"name": "Merge1"
},
{
"parameters": {
"language": "pythonNative",
"pythonCode": "import json\nimport base64\n\noutput_items = []\nall_data = []\n\n# Collecte toutes les donn\u00e9es JSON entrantes (items)\nfor item in _items:\n all_data.append(item['json'])\n\n# Convertit le tableau d'objets JSON en une cha\u00eene JSON format\u00e9e\n# s'assurer qu'on encode en UTF-8 pour la compatibilit\u00e9\njson_string = json.dumps(all_data, indent=2, ensure_ascii=False)\njson_bytes = json_string.encode('utf8')\n\n# Cr\u00e9e les donn\u00e9es binaires au format attendu par n8n (base64)\n# Le nom du champ binaire doit \u00eatre unique, ex: 'json_output'\nbinary_data = {\n 'json_output': {\n # Encode en base64 pour le transfert\n 'data': base64.b64encode(json_bytes).decode('utf8'), \n 'mimeType': 'application/json',\n 'fileName': 'faq_complete_rag_source.json',\n 'fileSize': len(json_bytes)\n }\n}\n\n# Cr\u00e9e l'objet de sortie avec les donn\u00e9es binaires\noutput_items.append({\n 'json': {'success': True, 'message': 'JSON converti en binaire'},\n 'binary': binary_data\n})\n\nreturn output_items"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1616,
-240
],
"id": "288e023a-bd03-4fec-ac93-87c3ef8cd082",
"name": "Create file context"
},
{
"parameters": {
"dataTableId": {
"__rl": true,
"value": "6bJjcVcg9rJne4UJ",
"mode": "list",
"cachedResultName": "faq",
"cachedResultUrl": "/projects/yJGMCjVHH04zJMly/datatables/6bJjcVcg9rJne4UJ"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"question": "={{ $json.question }}",
"answer": "={{ $json.data }}"
},
"matchingColumns": [],
"schema": [
{
"id": "question",
"displayName": "question",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "answer",
"displayName": "answer",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
1584,
112
],
"id": "df4335ba-af06-4fc2-b9aa-57fd845979fd",
"name": "Save question / answer"
},
{
"parameters": {
"operation": "get",
"dataTableId": {
"__rl": true,
"value": "6bJjcVcg9rJne4UJ",
"mode": "list",
"cachedResultName": "faq",
"cachedResultUrl": "/projects/yJGMCjVHH04zJMly/datatables/6bJjcVcg9rJne4UJ"
},
"matchType": "allConditions",
"filters": {
"conditions": [
{
"keyName": "question",
"keyValue": "={{ $json.question }}"
}
]
}
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
544,
96
],
"id": "99f7a78b-62f6-498d-9373-0741d97e96e8",
"name": "Get row(s)",
"alwaysOutputData": true
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 3
},
"conditions": [
{
"id": "56a3c12e-911b-4144-88ea-571b5f0d699b",
"leftValue": "={{ $json.id }}",
"rightValue": "",
"operator": {
"type": "number",
"operation": "notEmpty",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.3,
"position": [
752,
96
],
"id": "199a10fe-26ae-471f-95ed-2b4e981577df",
"name": "If question exists"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "3de5c651-80a8-44bc-9221-8dd3549c7a26",
"name": "data",
"value": "={{ $json.data }}",
"type": "string"
},
{
"id": "3a8ef59f-b67e-474d-af62-8865f47894b4",
"name": "question",
"value": "={{ $('Loop Over Questions').item.json.question }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1392,
112
],
"id": "4d36a9ed-865b-4199-ab73-07161cd60a62",
"name": "Rebuild data"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "4baf92a0-091c-427e-a50f-aae3324001d8",
"name": "data",
"value": "={{ $('Rebuild data').item.json.data }}",
"type": "string"
},
{
"id": "0c04d064-da0f-41bd-b98e-058f9c761062",
"name": "question",
"value": "={{ $('Rebuild data').item.json.question }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1792,
112
],
"id": "7e06d6c9-7aa9-488d-84e9-4331865062e9",
"name": "Build response"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "d3518942-62c5-4452-a9b9-5823608764df",
"name": "answer",
"value": "={{ $json.answer }}",
"type": "string"
},
{
"id": "6f05e761-a887-49a4-aced-c3241005c436",
"name": "question",
"value": "={{ $json.question }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1408,
-240
],
"id": "9e520a50-3b69-4efd-abb7-5dd107e90fdc",
"name": "Edit Fields"
}
],
"connections": {
"Manual Trigger": {
"main": [
[
{
"node": "Get FAQ first page",
"type": "main",
"index": 0
}
]
]
},
"Mistral Chat Model 1": {
"ai_languageModel": [
[
{
"node": "Extract categories",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Mistral Chat Model 2": {
"ai_languageModel": [
[
{
"node": "Extract questions / answers",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Mistral Chat Model 3": {
"ai_languageModel": [
[
{
"node": "Extract answer",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Get FAQ first page": {
"main": [
[
{
"node": "Extract categories",
"type": "main",
"index": 0
}
]
]
},
"Extract categories": {
"main": [
[
{
"node": "Parser categories",
"type": "main",
"index": 0
}
]
]
},
"Parser categories": {
"main": [
[
{
"node": "Get questions / answers url by category",
"type": "main",
"index": 0
}
]
]
},
"Get questions / answers url by category": {
"main": [
[
{
"node": "Extract questions / answers",
"type": "main",
"index": 0
}
]
]
},
"Extract questions / answers": {
"main": [
[
{
"node": "Parser questions / answers",
"type": "main",
"index": 0
}
]
]
},
"Parser questions / answers": {
"main": [
[
{
"node": "Loop Over Questions",
"type": "main",
"index": 0
}
]
]
},
"Get answer": {
"main": [
[
{
"node": "Rebuild data",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Questions": {
"main": [
[
{
"node": "Extract answer",
"type": "main",
"index": 0
},
{
"node": "Merge1",
"type": "main",
"index": 1
}
],
[
{
"node": "Get row(s)",
"type": "main",
"index": 0
}
]
]
},
"Wait": {
"main": [
[
{
"node": "Get answer",
"type": "main",
"index": 0
}
]
]
},
"Extract answer": {
"main": [
[
{
"node": "Parse answer",
"type": "main",
"index": 0
}
]
]
},
"Parse answer": {
"main": [
[
{
"node": "Merge1",
"type": "main",
"index": 0
}
]
]
},
"Merge1": {
"main": [
[
{
"node": "Edit Fields",
"type": "main",
"index": 0
}
]
]
},
"Create file context": {
"main": [
[
{
"node": "Upload file",
"type": "main",
"index": 0
}
]
]
},
"Save question / answer": {
"main": [
[
{
"node": "Build response",
"type": "main",
"index": 0
}
]
]
},
"Get row(s)": {
"main": [
[
{
"node": "If question exists",
"type": "main",
"index": 0
}
]
]
},
"If question exists": {
"main": [
[
{
"node": "Loop Over Questions",
"type": "main",
"index": 0
}
],
[
{
"node": "Wait",
"type": "main",
"index": 0
}
]
]
},
"Rebuild data": {
"main": [
[
{
"node": "Save question / answer",
"type": "main",
"index": 0
}
]
]
},
"Build response": {
"main": [
[
{
"node": "Loop Over Questions",
"type": "main",
"index": 0
}
]
]
},
"Edit Fields": {
"main": [
[
{
"node": "Create file context",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1",
"availableInMCP": false
},
"versionId": "93ba1de9-f9e7-438a-aee7-446203760439",
"meta": {
"templateCredsSetupCompleted": true
},
"id": "9u8lhjFWHBTpcyR6",
"tags": []
}
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.
googleDriveOAuth2ApimistralCloudApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
rag_faq_extractor. Uses lmChatMistralCloud, googleDrive, httpRequest, chainLlm. Event-driven trigger; 24 nodes.
Source: https://github.com/akira-dev/n8n-workflows/blob/main/workflows/rag_faq_extractor.json — 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.
Content Creators E-commerce Stores Marketing Team
Episode 11: AI shorts factory app. Uses httpRequest, googleSheets, lmChatOpenAi, lmChatOllama. Event-driven trigger; 96 nodes.
The best content automation template in the market is now even better—with “deep research” on time-sensitive topics\! Unlike most n8n content automation templates that are mainly for “demo purposes,”
My workflow 53. Uses formTrigger, httpRequest, lmChatOpenAi, form. Event-driven trigger; 74 nodes.
Episode 23: UGC with nanobanana. Uses lmChatOpenAi, lmChatOllama, lmChatDeepSeek, lmChatOpenRouter. Event-driven trigger; 74 nodes.