多源采集
高级
这是一个Miscellaneous、AI RAG、Multimodal AI领域的自动化工作流,包含 23 个节点。主要使用 Set、Code、HttpRequest、GoogleSheets、McpClientTool 等节点。 网络研究助手:基于Gemini AI的自动化搜索和抓取,生成电子表格报告
前置要求
- •可能需要目标 API 的认证凭证
- •Google Sheets API 凭证
- •Google Gemini API Key
使用的节点 (23 个)
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"id": "SjiPE2lVXmmyh7Ca",
"meta": {
"instanceId": "7578372eeadee5ee5414cdf5a06141eebec63e21f295454563ddce7b1217363f",
"templateCredsSetupCompleted": true
},
"name": "多源采集",
"tags": [],
"nodes": [
{
"id": "bf0013da-2066-45de-8833-fa2927728f00",
"name": "当收到聊天消息时",
"type": "@n8n/n8n-nodes-langchain.chatTrigger",
"position": [
-288,
0
],
"webhookId": "18e5e55a-53be-4afb-adc5-bdc4dabfa067",
"parameters": {
"options": {}
},
"typeVersion": 1.3
},
{
"id": "9fe3e0e0-f5ac-4018-90b7-f2e4fc7b207d",
"name": "简单记忆",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"position": [
224,
144
],
"parameters": {
"contextWindowLength": 30
},
"typeVersion": 1.3
},
{
"id": "c9e95768-ea7c-43f0-b6fd-a824fc64d60d",
"name": "Google Gemini聊天模型",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
80,
144
],
"parameters": {
"options": {}
},
"credentials": {
"googlePalmApi": {
"id": "89mVPG21GxPFECbN",
"name": "Google Gemini(PaLM) Api account"
}
},
"typeVersion": 1
},
{
"id": "cd7be0c8-f708-42f8-8411-a3622c25a0bf",
"name": "Firecrawl列表",
"type": "n8n-nodes-mcp.mcpClientTool",
"position": [
672,
352
],
"parameters": {},
"credentials": {
"mcpClientApi": {
"id": "aFCnpjjzHv0KPnei",
"name": "MCP: Firecrawl"
}
},
"typeVersion": 1
},
{
"id": "4cdda777-345c-4129-9ada-1a9c01b9a104",
"name": "Firecrawl执行",
"type": "n8n-nodes-mcp.mcpClientTool",
"position": [
672,
464
],
"parameters": {
"toolName": "={{ \n$fromAI(\"tool\", \"the selected tool to use\")\n}}",
"operation": "executeTool",
"toolParameters": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Tool_Parameters', ``, 'json') }}"
},
"credentials": {
"mcpClientApi": {
"id": "aFCnpjjzHv0KPnei",
"name": "MCP: Firecrawl"
}
},
"typeVersion": 1
},
{
"id": "35a550c1-8fb7-40c3-af16-bb059c6d1947",
"name": "Brave列表",
"type": "n8n-nodes-mcp.mcpClientTool",
"position": [
768,
352
],
"parameters": {},
"credentials": {
"mcpClientApi": {
"id": "wzdpQy5uTbYZQiko",
"name": "MCP: Brave"
}
},
"typeVersion": 1
},
{
"id": "ecd7944c-0de2-4447-b640-7a7caaa30705",
"name": "Brave执行",
"type": "n8n-nodes-mcp.mcpClientTool",
"position": [
768,
464
],
"parameters": {
"toolName": "={{\n$fromAI(\"tool\", \"the selected tool to use\")\n}}",
"operation": "executeTool",
"toolParameters": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Tool_Parameters', ``, 'json') }}"
},
"credentials": {
"mcpClientApi": {
"id": "wzdpQy5uTbYZQiko",
"name": "MCP: Brave"
}
},
"typeVersion": 1
},
{
"id": "3041cd71-2131-4cf5-b21b-7b7decc0a4bb",
"name": "Apify列表",
"type": "n8n-nodes-mcp.mcpClientTool",
"position": [
864,
464
],
"parameters": {},
"credentials": {
"mcpClientApi": {
"id": "0HMXUEhEUFLuWqlS",
"name": "MCP : Apify"
}
},
"typeVersion": 1
},
{
"id": "1ba3c633-998b-4ab2-83c1-c6dd0e7c6679",
"name": "Apify执行",
"type": "n8n-nodes-mcp.mcpClientTool",
"position": [
864,
352
],
"parameters": {
"toolName": "={{ $fromAI(\"tool\", \"the selected tool to use\") }}",
"operation": "executeTool",
"toolParameters": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Tool_Parameters', ``, 'json') }}"
},
"credentials": {
"mcpClientApi": {
"id": "aFCnpjjzHv0KPnei",
"name": "MCP: Firecrawl"
}
},
"typeVersion": 1
},
{
"id": "73031a7a-6338-4683-a6e3-efee3819f89e",
"name": "数据增强请求",
"type": "n8n-nodes-base.httpRequest",
"position": [
1296,
0
],
"parameters": {
"url": "=https://sheets.googleapis.com/v4/spreadsheets/{{ $json.spreadsheetId }}/values:batchUpdate",
"method": "POST",
"options": {},
"jsonBody": "={\n \"valueInputOption\": \"USER_ENTERED\",\n \"data\": {{ JSON.stringify($json.valueRanges) }}\n}",
"sendBody": true,
"specifyBody": "json"
},
"typeVersion": 4.2
},
{
"id": "9a7f6cbe-a132-4fef-9af8-b9851227faf6",
"name": "Gemini研究编排器",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
208,
0
],
"parameters": {
"options": {
"systemMessage": "You are a helpful assistant\n\nUse Brave to search into the web\nUse Firecrawl to scrape websites\nUse Apify to scrape websites\n\nthe process is to use the tool node first then the execute node.\n\nAlways refer to the list of tools before attempting to access or use the execute tools"
}
},
"typeVersion": 2.2
},
{
"id": "acf4a537-627a-4d20-8b02-215f8075900b",
"name": "创建研究报告",
"type": "n8n-nodes-base.googleSheets",
"position": [
704,
0
],
"parameters": {
"title": "scrapped ",
"options": {},
"resource": "spreadsheet"
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "FglkISb2md6llLsJ",
"name": "Google Sheets account"
}
},
"typeVersion": 4.7
},
{
"id": "13e00e06-9b7e-4fb2-bbbd-9e7211de9e96",
"name": "格式化研究数据",
"type": "n8n-nodes-base.code",
"position": [
880,
0
],
"parameters": {
"jsCode": "// Version sécurisée qui gère les feuilles existantes\nconst agentOutput = $('Gemini Research Orchestrator').item.json.output;\nconst spreadsheetId = $('Create Research Report').item.json.spreadsheetId;\n\n// Fonction pour parser le markdown (identique)\nfunction parseAgentOutput(output) {\n const lines = output.split('\\n').filter(line => line.trim() !== '');\n const data = {\n title: '',\n categories: [],\n jobs: []\n };\n \n let currentSection = '';\n let inTable = false;\n let tableHeaders = [];\n \n for (let i = 0; i < lines.length; i++) {\n const line = lines[i].trim();\n \n if (line.startsWith('Voici les données extraites')) {\n data.title = line.replace(/\\*\\*/g, '').replace('Voici les données extraites du site ', '').replace(/[`:`]/g, '');\n }\n \n if (line.startsWith('**') && line.endsWith(':**')) {\n currentSection = line.replace(/\\*\\*/g, '').replace(':', '');\n inTable = false;\n }\n \n if (currentSection === 'Catégories d\\'emploi' && line.startsWith('* ')) {\n data.categories.push(line.replace('* ', ''));\n }\n \n if (line.startsWith('|') && !inTable) {\n const headers = line.split('|').map(h => h.trim()).filter(h => h !== '');\n if (headers.length > 0) {\n tableHeaders = headers;\n inTable = true;\n i++;\n continue;\n }\n }\n \n if (inTable && line.startsWith('|')) {\n const cells = line.split('|').map(c => c.trim()).filter(c => c !== '');\n if (cells.length === tableHeaders.length) {\n const job = {};\n tableHeaders.forEach((header, index) => {\n job[header] = cells[index] || '';\n });\n data.jobs.push(job);\n }\n }\n }\n \n return data;\n}\n\n// Fonction pour créer ou mettre à jour une feuille\nfunction createOrUpdateSheet(sheetName, sheetId, properties = {}) {\n if (sheetId === 0) {\n // Pour la feuille par défaut (ID 0), on la met à jour\n return {\n updateSheetProperties: {\n properties: {\n sheetId: sheetId,\n title: sheetName,\n gridProperties: {\n rowCount: 1000,\n columnCount: 26\n },\n ...properties\n },\n fields: 'title,tabColor,gridProperties'\n }\n };\n } else {\n // Pour les nouvelles feuilles, on les crée\n return {\n addSheet: {\n properties: {\n sheetId: sheetId,\n title: sheetName,\n gridProperties: {\n rowCount: 1000,\n columnCount: 26\n },\n ...properties\n }\n }\n };\n }\n}\n\n// Fonction pour ajouter des données dans une feuille\nfunction addSheetData(sheetName, range, values, majorDimension = 'ROWS') {\n return {\n range: `'${sheetName}'!${range}`,\n majorDimension: majorDimension,\n values: values\n };\n}\n\n// Fonction pour formater les cellules\nfunction formatCells(sheetId, range, format) {\n return {\n repeatCell: {\n range: {\n sheetId: sheetId,\n startRowIndex: range.startRow,\n endRowIndex: range.endRow,\n startColumnIndex: range.startCol,\n endColumnIndex: range.endCol\n },\n cell: {\n userEnteredFormat: format\n },\n fields: 'userEnteredFormat'\n }\n };\n}\n\n// Fonction pour obtenir les styles de formatage\nfunction getTextFormat(style) {\n const formats = {\n 'TITLE': {\n textFormat: {\n bold: true,\n fontSize: 16,\n foregroundColor: { red: 0.1, green: 0.1, blue: 0.1 }\n },\n horizontalAlignment: 'CENTER',\n backgroundColor: { red: 0.85, green: 0.85, blue: 0.95 }\n },\n 'SECTION_HEADER': {\n textFormat: {\n bold: true,\n fontSize: 14,\n foregroundColor: { red: 0.2, green: 0.2, blue: 0.2 }\n },\n backgroundColor: { red: 0.9, green: 0.9, blue: 0.9 }\n },\n 'TABLE_HEADER': {\n textFormat: {\n bold: true,\n fontSize: 11,\n foregroundColor: { red: 1, green: 1, blue: 1 }\n },\n backgroundColor: { red: 0.2, green: 0.4, blue: 0.8 },\n horizontalAlignment: 'CENTER',\n borders: {\n top: { style: 'SOLID', width: 2 },\n bottom: { style: 'SOLID', width: 2 },\n left: { style: 'SOLID', width: 1 },\n right: { style: 'SOLID', width: 1 }\n }\n },\n 'TABLE_CELL': {\n textFormat: {\n fontSize: 10,\n foregroundColor: { red: 0.1, green: 0.1, blue: 0.1 }\n },\n borders: {\n top: { style: 'SOLID', width: 1 },\n bottom: { style: 'SOLID', width: 1 },\n left: { style: 'SOLID', width: 1 },\n right: { style: 'SOLID', width: 1 }\n },\n verticalAlignment: 'TOP'\n },\n 'CATEGORY': {\n textFormat: {\n fontSize: 11,\n foregroundColor: { red: 0.3, green: 0.3, blue: 0.3 }\n },\n backgroundColor: { red: 0.95, green: 0.98, blue: 0.95 }\n }\n };\n return formats[style] || formats['TABLE_CELL'];\n}\n\n// Parsing des données\nlet parsedData;\ntry {\n parsedData = parseAgentOutput(agentOutput);\n} catch (error) {\n throw new Error(`Erreur lors du parsing des données: ${error.message}`);\n}\n\n// Construction des requêtes et données\nconst requests = [];\nconst valueRanges = [];\n\ntry {\n // D'abord, effacer le contenu de la feuille par défaut\n requests.push({\n updateCells: {\n range: {\n sheetId: 0\n },\n fields: '*'\n }\n });\n\n // 1. Mise à jour de la feuille par défaut (ID 0) -> \"Résumé\"\n requests.push(createOrUpdateSheet('Resume', 0, {\n tabColor: { red: 0.2, green: 0.5, blue: 0.8 }\n }));\n\n // Données de la feuille Résumé\n const summaryData = [\n [parsedData.title || 'Données extraites'],\n [''],\n ['Résumé des données:'],\n [`Nombre de catégories: ${parsedData.categories.length}`],\n [`Nombre d'emplois: ${parsedData.jobs.length}`],\n [''],\n ['Catégories d\\'emploi:']\n ];\n\n parsedData.categories.forEach(category => {\n summaryData.push([`• ${category}`]);\n });\n\n valueRanges.push(addSheetData('Resume', 'A1', summaryData));\n\n // Formatage de la feuille Résumé\n requests.push(formatCells(0, { startRow: 0, endRow: 1, startCol: 0, endCol: 3 }, getTextFormat('TITLE')));\n requests.push(formatCells(0, { startRow: 2, endRow: 3, startCol: 0, endCol: 3 }, getTextFormat('SECTION_HEADER')));\n requests.push(formatCells(0, { startRow: 6, endRow: 7, startCol: 0, endCol: 3 }, getTextFormat('SECTION_HEADER')));\n \n const categoryStartRow = 7;\n const categoryEndRow = categoryStartRow + parsedData.categories.length;\n requests.push(formatCells(0, { \n startRow: categoryStartRow, \n endRow: categoryEndRow, \n startCol: 0, \n endCol: 2 \n }, getTextFormat('CATEGORY')));\n\n // 2. Création de la feuille \"Catégories\"\n requests.push(createOrUpdateSheet('Categories', 1, {\n tabColor: { red: 0.8, green: 0.9, blue: 0.7 }\n }));\n\n const categoriesData = [\n ['Catégories d\\'emploi'],\n [''],\n ['Catégorie', 'Numéro']\n ];\n\n parsedData.categories.forEach((category, index) => {\n categoriesData.push([category, index + 1]);\n });\n\n valueRanges.push(addSheetData('Categories', 'A1', categoriesData));\n\n requests.push(formatCells(1, { startRow: 0, endRow: 1, startCol: 0, endCol: 2 }, getTextFormat('TITLE')));\n requests.push(formatCells(1, { startRow: 2, endRow: 3, startCol: 0, endCol: 2 }, getTextFormat('TABLE_HEADER')));\n \n if (parsedData.categories.length > 0) {\n requests.push(formatCells(1, { \n startRow: 3, \n endRow: 3 + parsedData.categories.length, \n startCol: 0, \n endCol: 2 \n }, getTextFormat('TABLE_CELL')));\n }\n\n // 3. Création de la feuille \"Emplois\"\n requests.push(createOrUpdateSheet('Emplois', 2, {\n tabColor: { red: 0.9, green: 0.7, blue: 0.8 }\n }));\n\n if (parsedData.jobs.length > 0) {\n const jobHeaders = Object.keys(parsedData.jobs[0]);\n const jobsData = [\n ['Liste des emplois disponibles'],\n [''],\n jobHeaders\n ];\n\n parsedData.jobs.forEach(job => {\n const jobRow = jobHeaders.map(header => job[header] || '');\n jobsData.push(jobRow);\n });\n\n valueRanges.push(addSheetData('Emplois', 'A1', jobsData));\n\n requests.push(formatCells(2, { startRow: 0, endRow: 1, startCol: 0, endCol: jobHeaders.length }, getTextFormat('TITLE')));\n requests.push(formatCells(2, { startRow: 2, endRow: 3, startCol: 0, endCol: jobHeaders.length }, getTextFormat('TABLE_HEADER')));\n \n if (parsedData.jobs.length > 0) {\n requests.push(formatCells(2, { \n startRow: 3, \n endRow: 3 + parsedData.jobs.length, \n startCol: 0, \n endCol: jobHeaders.length \n }, getTextFormat('TABLE_CELL')));\n }\n }\n\n // 4. Création de la feuille \"Statistiques\"\n requests.push(createOrUpdateSheet('Statistiques', 3, {\n tabColor: { red: 0.95, green: 0.8, blue: 0.6 }\n }));\n\n const companyCount = [...new Set(parsedData.jobs.map(job => job.Entreprise || job.Company || ''))].length;\n const roleTypes = {};\n \n parsedData.jobs.forEach(job => {\n const role = job.Rôle || job.Role || '';\n const roleType = role.split(' ')[0];\n roleTypes[roleType] = (roleTypes[roleType] || 0) + 1;\n });\n\n const statsData = [\n ['Statistiques des données'],\n [''],\n ['Métrique', 'Valeur'],\n ['Nombre total d\\'emplois', parsedData.jobs.length],\n ['Nombre d\\'entreprises uniques', companyCount],\n ['Nombre de catégories', parsedData.categories.length],\n [''],\n ['Types de rôles les plus fréquents:'],\n ['Type de rôle', 'Occurrences']\n ];\n\n const sortedRoleTypes = Object.entries(roleTypes)\n .sort(([,a], [,b]) => b - a)\n .slice(0, 10);\n\n sortedRoleTypes.forEach(([role, count]) => {\n statsData.push([role, count]);\n });\n\n valueRanges.push(addSheetData('Statistiques', 'A1', statsData));\n\n requests.push(formatCells(3, { startRow: 0, endRow: 1, startCol: 0, endCol: 2 }, getTextFormat('TITLE')));\n requests.push(formatCells(3, { startRow: 2, endRow: 3, startCol: 0, endCol: 2 }, getTextFormat('TABLE_HEADER')));\n requests.push(formatCells(3, { startRow: 7, endRow: 8, startCol: 0, endCol: 2 }, getTextFormat('SECTION_HEADER')));\n requests.push(formatCells(3, { startRow: 8, endRow: 9, startCol: 0, endCol: 2 }, getTextFormat('TABLE_HEADER')));\n\n // Auto-redimensionnement des colonnes\n for (let i = 0; i <= 3; i++) {\n requests.push({\n autoResizeDimensions: {\n dimensions: {\n sheetId: i,\n dimension: 'COLUMNS',\n startIndex: 0,\n endIndex: 10\n }\n }\n });\n }\n\n} catch (error) {\n console.error('Erreur lors de la génération du contenu:', error);\n throw new Error(`Erreur lors de la génération du contenu: ${error.message}`);\n}\n\n// Validation finale des données\nif (!requests || requests.length === 0) {\n throw new Error('Aucune requête générée - vérifiez les données d\\'entrée');\n}\n\nif (!valueRanges || valueRanges.length === 0) {\n throw new Error('Aucune donnée générée - vérifiez les données d\\'entrée');\n}\n\n// Retour des données pour l'API Google Sheets\nreturn {\n json: {\n spreadsheetId: spreadsheetId,\n requests: requests,\n valueRanges: valueRanges,\n totalRequests: requests.length,\n totalValueRanges: valueRanges.length,\n sheetsCreated: 4,\n dataProcessed: {\n title: parsedData.title,\n categoriesCount: parsedData.categories.length,\n jobsCount: parsedData.jobs.length,\n companiesCount: [...new Set(parsedData.jobs.map(job => job.Entreprise || job.Company || ''))].length\n }\n }\n};"
},
"typeVersion": 2
},
{
"id": "eccede4d-c790-4b60-a3cd-5e9f29ac8f0e",
"name": "填充研究报告",
"type": "n8n-nodes-base.httpRequest",
"position": [
1072,
0
],
"parameters": {
"url": "=https://sheets.googleapis.com/v4/spreadsheets/{{ $json.spreadsheetId }}:batchUpdate",
"method": "POST",
"options": {},
"jsonBody": "={\n \"requests\": {{ JSON.stringify($json.requests) }}\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleSheetsOAuth2Api"
},
"credentials": {
"googleDocsOAuth2Api": {
"id": "osBJI4KIPRu07ngs",
"name": "Google Docs account"
},
"googleSheetsOAuth2Api": {
"id": "bkpmM7RgsOJtIBT5",
"name": "Google Sheets account 2"
}
},
"typeVersion": 4.2
},
{
"id": "c9603254-752b-4f86-8d77-e6231699094b",
"name": "最终输出数据",
"type": "n8n-nodes-base.set",
"position": [
1488,
0
],
"parameters": {
"mode": "raw",
"options": {},
"jsonOutput": "{\n \"error_message\": \"{{ $json.error.message }}\",\n \"error_code\": \"{{ $json.error.code }}\",\n \"spreadsheet_id\": \"{{ $('Code').item.json.spreadsheetId }}\",\n \"timestamp\": \"{{ new Date().toISOString() }}\"\n}"
},
"typeVersion": 3.4
},
{
"id": "0c07aba4-88c4-4ddd-93e8-26057f6104f8",
"name": "便签",
"type": "n8n-nodes-base.stickyNote",
"position": [
-544,
-96
],
"parameters": {
"color": 4,
"width": 400,
"height": 256,
"content": "## 入口点:"
},
"typeVersion": 1
},
{
"id": "4a113616-2e51-4bb7-8995-1c657f12fa9b",
"name": "便签 1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-80,
-320
],
"parameters": {
"color": 4,
"width": 256,
"height": 128,
"content": "## ⚙️ 前提条件"
},
"typeVersion": 1
},
{
"id": "fadd1418-2831-4856-9913-de61ec11d418",
"name": "便签 2",
"type": "n8n-nodes-base.stickyNote",
"position": [
240,
-320
],
"parameters": {
"color": 4,
"height": 128,
"content": "## 📊 数据流"
},
"typeVersion": 1
},
{
"id": "6afc44f5-db99-46a8-96ca-5e788e48bfff",
"name": "便签 3",
"type": "n8n-nodes-base.stickyNote",
"position": [
528,
-320
],
"parameters": {
"color": 4,
"width": 272,
"height": 112,
"content": "## ⚠️ 错误处理"
},
"typeVersion": 1
},
{
"id": "104c3b3a-ae84-4ef5-99fb-b84cf599975a",
"name": "便签 4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-80,
-112
],
"parameters": {
"color": 5,
"width": 544,
"height": 384,
"content": "## 编排"
},
"typeVersion": 1
},
{
"id": "4bdd58e3-eddd-4fa3-82f4-bc84ec5498fc",
"name": "便签 5",
"type": "n8n-nodes-base.stickyNote",
"position": [
240,
288
],
"parameters": {
"width": 752,
"height": 304,
"content": "## 数据采集工具"
},
"typeVersion": 1
},
{
"id": "509c0f30-e634-46d5-83d2-b4aafd8090b8",
"name": "便签6",
"type": "n8n-nodes-base.stickyNote",
"position": [
656,
-160
],
"parameters": {
"color": 3,
"width": 544,
"height": 304,
"content": "## 报告生成"
},
"typeVersion": 1
},
{
"id": "7dd445d7-2785-4f0a-a938-e9e9e962e929",
"name": "便签7",
"type": "n8n-nodes-base.stickyNote",
"position": [
1264,
-160
],
"parameters": {
"color": 7,
"width": 432,
"height": 304,
"content": "## 后处理"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "94fda3e6-3671-42e8-9f8a-d9d7688722eb",
"connections": {
"Apify list": {
"ai_tool": [
[
{
"node": "Gemini Research Orchestrator",
"type": "ai_tool",
"index": 0
}
]
]
},
"Brave list": {
"ai_tool": [
[
{
"node": "Gemini Research Orchestrator",
"type": "ai_tool",
"index": 0
}
]
]
},
"Apify execute": {
"ai_tool": [
[
{
"node": "Gemini Research Orchestrator",
"type": "ai_tool",
"index": 0
}
]
]
},
"Brave execute": {
"ai_tool": [
[
{
"node": "Gemini Research Orchestrator",
"type": "ai_tool",
"index": 0
}
]
]
},
"Simple Memory": {
"ai_memory": [
[
{
"node": "Gemini Research Orchestrator",
"type": "ai_memory",
"index": 0
}
]
]
},
"Firecrawl list": {
"ai_tool": [
[
{
"node": "Gemini Research Orchestrator",
"type": "ai_tool",
"index": 0
}
]
]
},
"Firecrawl execute": {
"ai_tool": [
[
{
"node": "Gemini Research Orchestrator",
"type": "ai_tool",
"index": 0
}
]
]
},
"Finalize Output Data": {
"main": [
[]
]
},
"Format Research Data": {
"main": [
[
{
"node": "Populate Research Report",
"type": "main",
"index": 0
}
]
]
},
"Create Research Report": {
"main": [
[
{
"node": "Format Research Data",
"type": "main",
"index": 0
}
]
]
},
"Data Enrichment Request": {
"main": [
[
{
"node": "Finalize Output Data",
"type": "main",
"index": 0
}
]
]
},
"Google Gemini Chat Model": {
"ai_languageModel": [
[
{
"node": "Gemini Research Orchestrator",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Populate Research Report": {
"main": [
[
{
"node": "Data Enrichment Request",
"type": "main",
"index": 0
}
]
]
},
"When chat message received": {
"main": [
[
{
"node": "Gemini Research Orchestrator",
"type": "main",
"index": 0
}
]
]
},
"Gemini Research Orchestrator": {
"main": [
[
{
"node": "Create Research Report",
"type": "main",
"index": 0
}
]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
这是一个高级难度的工作流,适用于Miscellaneous、AI RAG、Multimodal AI等场景。适合高级用户,包含 16+ 个节点的复杂工作流
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
使用 OpenAI 嵌入的 BigQuery RAG
使用 BigQuery RAG 和 OpenAI 回答文档相关问题
Set
Http Request
Agent
+6
24 节点Dataki
Miscellaneous
竞争对手内容差距分析器:自动化网站主题映射
使用Gemini AI、Apify和Google Sheets分析竞争对手内容差距
If
Set
Code
+10
30 节点Mychel Garzon
Miscellaneous
房产搜索器爬虫助手
使用 PropertyFinder.ae、OpenRouter 和 SerpAPI 通过 AI 回答房地产问题
If
Set
Code
+9
18 节点George Zargaryan
Miscellaneous
上下文混合RAG AI文案
Google Drive到Supabase上下文向量数据库同步用于RAG应用
If
Set
Code
+25
76 节点Michael Taleb
AI RAG
使用Telegram、Whisper和Gemini实现Home Assistant语音与文本控制
使用Telegram、Whisper和Gemini实现Home Assistant语音与文本控制
If
Set
Code
+10
30 节点Arkadiusz
Miscellaneous
基于网站内容和Airtable数据构建用于RAG应用的聊天机器人
基于Pinecone、Airtable和OpenAI的网站内容聊天机器人(RAG应用)
Set
Code
Markdown
+15
27 节点Alok Kumar
AI RAG
工作流信息
难度等级
高级
节点数量23
分类3
节点类型10
作者
franck fambou
@franck-fAs a student in Data Science & Artificial Intelligence, I design intelligent automations that combine no-code and AI to optimize business processes. I share innovative workflows to democratize automation.
外部链接
在 n8n.io 上查看 →
分享此工作流