导出 n8n
高级
这是一个Personal Productivity, Multimodal AI领域的自动化工作流,包含 17 个节点。主要使用 If, Set, Code, Switch, Webhook 等节点。 使用LINE和OpenAI Vision从图片记录食物卡路里到Google Sheets
前置要求
- •HTTP Webhook 端点(n8n 会自动生成)
- •可能需要目标 API 的认证凭证
- •Google Sheets API 凭证
- •OpenAI API Key
使用的节点 (17)
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"id": "HzZvyjb6riqHb2FR",
"meta": {
"instanceId": "9101df148a9ab5ba09dd343a0c584806dbd6c3b74e74be8e97699184269b6877"
},
"name": "导出 n8n",
"tags": [],
"nodes": [
{
"id": "74a3253b-68d1-4745-85a1-70f5fa3260a9",
"name": "切换",
"type": "n8n-nodes-base.switch",
"position": [
-592,
48
],
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "80b1a421-efcd-487e-8c18-925496da9b0c",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.body.events[0].message.type }}",
"rightValue": "text"
}
]
}
},
{
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "c124e4cd-78b0-4ce1-bf72-26806f7211e8",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.body.events[0].message.type }}",
"rightValue": "image"
}
]
}
}
]
},
"options": {
"fallbackOutput": "extra"
}
},
"typeVersion": 3.2
},
{
"id": "adf17e8b-4e45-4ad4-90e9-208b5bf6207f",
"name": "AI 代理",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
160,
-160
],
"parameters": {
"text": "={{ $json.text }}",
"options": {
"systemMessage": "=You are an AI assistant. Your job is to respond to user messages."
},
"promptType": "define"
},
"typeVersion": 2.1
},
{
"id": "ef15eb25-64d9-4c30-becc-7f338d46ce55",
"name": "OpenAI Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
32,
48
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"id": "mO23EZGRXh9cFi9G",
"name": "OpenAi account 2"
}
},
"typeVersion": 1.2
},
{
"id": "17e136f4-34f7-42c8-9793-19d13610aa49",
"name": "分析图片",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
-96,
272
],
"parameters": {
"text": "=Estimate calories only if the item in this image is a food item, and output the calories in the following simple JSON format:\n\n[{\n\"dishName\": \"result\",\n\"calories\": \"result\",\n}]\n\nDo not output anything but this JSON only if it is food.",
"modelId": {
"__rl": true,
"mode": "list",
"value": "chatgpt-4o-latest",
"cachedResultName": "CHATGPT-4O-LATEST"
},
"options": {},
"resource": "image",
"inputType": "base64",
"operation": "analyze"
},
"credentials": {
"openAiApi": {
"id": "mO23EZGRXh9cFi9G",
"name": "OpenAi account 2"
}
},
"typeVersion": 1.8
},
{
"id": "0359b260-8639-475b-8d47-cc76e004f027",
"name": "编辑字段1",
"type": "n8n-nodes-base.set",
"position": [
576,
272
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "6e9a99a3-62b1-4121-b7d7-148eaebbe9ba",
"name": "output",
"type": "string",
"value": "={{ $json.message }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "0535be0a-4aac-48a8-8909-41abca4944a0",
"name": "简单记忆",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"position": [
176,
48
],
"parameters": {
"sessionKey": "={{ $('LINE webhook').item.json.body.events[0].source.userId }}",
"sessionIdType": "customKey"
},
"typeVersion": 1.3
},
{
"id": "2851ca68-76c5-4b97-910d-2d4fa729754f",
"name": "代码",
"type": "n8n-nodes-base.code",
"position": [
352,
608
],
"parameters": {
"jsCode": "const inputData = $input.all();\nconst results = [];\n\nfor (let i = 0; i < inputData.length; i++) {\n try {\n\n let aiResponse = inputData[i].json.output || inputData[i].json.text || inputData[i].json.content || '';\n \n if (!aiResponse) {\n console.log(`アイテム ${i}: 空の応答をスキップ`);\n continue;\n }\n \n // 文字列の前後の空白を削除\n aiResponse = aiResponse.trim();\n \n // JSONの前後にある不要なテキストを削除\n // ```json や ``` で囲まれている場合の処理\n if (aiResponse.includes('```json')) {\n const jsonStart = aiResponse.indexOf('```json') + 7;\n const jsonEnd = aiResponse.indexOf('```', jsonStart);\n if (jsonEnd !== -1) {\n aiResponse = aiResponse.substring(jsonStart, jsonEnd).trim();\n }\n } else if (aiResponse.includes('```')) {\n const jsonStart = aiResponse.indexOf('```') + 3;\n const jsonEnd = aiResponse.indexOf('```', jsonStart);\n if (jsonEnd !== -1) {\n aiResponse = aiResponse.substring(jsonStart, jsonEnd).trim();\n }\n }\n \n // JSONの開始と終了を見つける\n const jsonStartIndex = aiResponse.indexOf('[');\n const jsonEndIndex = aiResponse.lastIndexOf(']');\n \n if (jsonStartIndex !== -1 && jsonEndIndex !== -1 && jsonEndIndex > jsonStartIndex) {\n const jsonString = aiResponse.substring(jsonStartIndex, jsonEndIndex + 1);\n \n try {\n // JSONをパース\n const parsedData = JSON.parse(jsonString);\n \n // 配列でない場合は配列に変換\n const dataArray = Array.isArray(parsedData) ? parsedData : [parsedData];\n \n // 各アイテムを処理\n dataArray.forEach((item, index) => {\n // 必要なフィールドが存在することを確認\n if (item && typeof item === 'object') {\n const processedItem = {\n dishName: item.dishName || item.dish_name || item.name || 'Unknown',\n calories: item.calories || item.calorie || item.cal || 0,\n // 元のデータも保持(デバッグ用)\n originalIndex: i,\n itemIndex: index,\n timestamp: new Date().toISOString()\n };\n \n // カロリーが数値でない場合は数値に変換を試行\n if (typeof processedItem.calories === 'string') {\n const numericCalories = parseInt(processedItem.calories.replace(/[^\\d]/g, ''));\n processedItem.calories = isNaN(numericCalories) ? 0 : numericCalories;\n }\n \n results.push({ json: processedItem });\n }\n });\n \n } catch (parseError) {\n console.log(`アイテム ${i}: JSON解析エラー - ${parseError.message}`);\n console.log(`問題のあるJSON文字列: ${jsonString}`);\n \n // JSONが無効な場合でも、手動でデータを抽出を試行\n const manualExtract = extractDataManually(aiResponse);\n if (manualExtract) {\n results.push({ json: manualExtract });\n }\n }\n } else {\n console.log(`アイテム ${i}: 有効なJSON構造が見つかりません`);\n \n // 手動でデータを抽出を試行\n const manualExtract = extractDataManually(aiResponse);\n if (manualExtract) {\n results.push({ json: manualExtract });\n }\n }\n \n } catch (error) {\n console.log(`アイテム ${i}: 処理エラー - ${error.message}`);\n \n // エラーが発生した場合でもデフォルト値で処理を継続\n results.push({\n json: {\n dishName: 'Error',\n calories: 0,\n error: error.message,\n originalIndex: i,\n timestamp: new Date().toISOString()\n }\n });\n }\n}\n\n// 手動でデータを抽出する関数\nfunction extractDataManually(text) {\n try {\n const dishMatch = text.match(/\"dishName\"\\s*:\\s*\"([^\"]+)\"/i) || \n text.match(/\"dish_name\"\\s*:\\s*\"([^\"]+)\"/i) ||\n text.match(/\"name\"\\s*:\\s*\"([^\"]+)\"/i);\n \n const caloriesMatch = text.match(/\"calories\"\\s*:\\s*\"?(\\d+)\"?/i) ||\n text.match(/\"calorie\"\\s*:\\s*\"?(\\d+)\"?/i) ||\n text.match(/\"cal\"\\s*:\\s*\"?(\\d+)\"?/i);\n \n if (dishMatch || caloriesMatch) {\n return {\n dishName: dishMatch ? dishMatch[1] : 'Unknown',\n calories: caloriesMatch ? parseInt(caloriesMatch[1]) : 0,\n extractedManually: true,\n timestamp: new Date().toISOString()\n };\n }\n } catch (error) {\n console.log('手動抽出エラー:', error.message);\n }\n return null;\n}\n\n// 結果が空の場合のデフォルト処理\nif (results.length === 0) {\n console.log('処理可能なデータが見つかりませんでした');\n results.push({\n json: {\n dishName: 'No Data',\n calories: 0,\n error: 'No valid data found',\n timestamp: new Date().toISOString()\n }\n });\n}\n\nconsole.log(`処理完了: ${results.length} 件のアイテムを変換しました`);\nreturn results;"
},
"typeVersion": 2
},
{
"id": "bff30c01-da43-463d-940e-b396d8237c61",
"name": "在表格中添加行",
"type": "n8n-nodes-base.googleSheets",
"position": [
608,
608
],
"parameters": {
"columns": {
"value": {
"cal": "={{ $json.calories }}",
"date": "={{ $now.format('yyyy-MM-dd') }}",
"menu": "={{ $json.dishName }}"
},
"schema": [
{
"id": "date",
"type": "string",
"display": true,
"required": false,
"displayName": "date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "menu",
"type": "string",
"display": true,
"required": false,
"displayName": "menu",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "cal",
"type": "string",
"display": true,
"required": false,
"displayName": "cal",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 1178520345,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1upzLlUvmXYgALLtUR6WEHUtxh064mDNrBVM-b3Of_vg/edit#gid=1178520345",
"cachedResultName": "11_test"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1upzLlUvmXYgALLtUR6WEHUtxh064mDNrBVM-b3Of_vg",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1upzLlUvmXYgALLtUR6WEHUtxh064mDNrBVM-b3Of_vg/edit?usp=drivesdk",
"cachedResultName": "kote2 n8n sheet"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "XH1Umk2FssMX8K1X",
"name": "Google Sheets account"
}
},
"typeVersion": 4.6
},
{
"id": "1bf7ef0f-1e8d-4e61-b3bd-aaaefcf15366",
"name": "代码1",
"type": "n8n-nodes-base.code",
"position": [
352,
272
],
"parameters": {
"jsCode": "// n8n Code node - AIエージェントからのJSON文字列をLINEメッセージに変換\nconst inputData = $input.all();\nconst results = [];\n\nfor (let i = 0; i < inputData.length; i++) {\n try {\n // AIエージェントからの出力を取得\n let aiResponse = inputData[i].json.output || inputData[i].json.text || inputData[i].json.content || '';\n \n // 空の場合はスキップ\n if (!aiResponse) {\n console.log(`アイテム ${i}: 空の応答をスキップ`);\n continue;\n }\n \n // 文字列の前後の空白を削除\n aiResponse = aiResponse.trim();\n \n // JSONデータを抽出する\n const menuItems = extractMenuData(aiResponse);\n \n if (menuItems && menuItems.length > 0) {\n // LINEメッセージを生成\n const lineMessage = generateLineMessage(menuItems);\n \n results.push({\n json: {\n message: lineMessage,\n menuCount: menuItems.length,\n totalCalories: menuItems.reduce((sum, item) => sum + item.calories, 0),\n timestamp: new Date().toISOString(),\n originalIndex: i\n }\n });\n \n console.log(`アイテム ${i}: ${menuItems.length}個のメニューを処理しました`);\n } else {\n // 食品が検出されなかった場合\n results.push({\n json: {\n message: \"画像から食品を検出できませんでした。\",\n menuCount: 0,\n totalCalories: 0,\n timestamp: new Date().toISOString(),\n originalIndex: i\n }\n });\n \n console.log(`アイテム ${i}: 食品が検出されませんでした`);\n }\n \n } catch (error) {\n console.log(`アイテム ${i}: 処理エラー - ${error.message}`);\n \n // エラーが発生した場合のデフォルトメッセージ\n results.push({\n json: {\n message: \"画像の解析でエラーが発生しました。もう一度お試しください。\",\n menuCount: 0,\n totalCalories: 0,\n error: error.message,\n timestamp: new Date().toISOString(),\n originalIndex: i\n }\n });\n }\n}\n\n// JSONデータを抽出する関数\nfunction extractMenuData(text) {\n const menuItems = [];\n \n try {\n // JSONの前後にある不要なテキストを削除\n let cleanText = text;\n \n // ```json や ``` で囲まれている場合の処理\n if (cleanText.includes('```json')) {\n const jsonStart = cleanText.indexOf('```json') + 7;\n const jsonEnd = cleanText.indexOf('```', jsonStart);\n if (jsonEnd !== -1) {\n cleanText = cleanText.substring(jsonStart, jsonEnd).trim();\n }\n } else if (cleanText.includes('```')) {\n const jsonStart = cleanText.indexOf('```') + 3;\n const jsonEnd = cleanText.indexOf('```', jsonStart);\n if (jsonEnd !== -1) {\n cleanText = cleanText.substring(jsonStart, jsonEnd).trim();\n }\n }\n \n // JSONの開始と終了を見つける\n const jsonStartIndex = cleanText.indexOf('[');\n const jsonEndIndex = cleanText.lastIndexOf(']');\n \n if (jsonStartIndex !== -1 && jsonEndIndex !== -1 && jsonEndIndex > jsonStartIndex) {\n const jsonString = cleanText.substring(jsonStartIndex, jsonEndIndex + 1);\n \n try {\n // JSONをパース\n const parsedData = JSON.parse(jsonString);\n \n // 配列でない場合は配列に変換\n const dataArray = Array.isArray(parsedData) ? parsedData : [parsedData];\n \n // 各アイテムを処理\n dataArray.forEach((item) => {\n if (item && typeof item === 'object') {\n const dishName = item.dishName || item.dish_name || item.name || 'Unknown';\n let calories = item.calories || item.calorie || item.cal || 0;\n \n // カロリーが文字列の場合は数値に変換\n if (typeof calories === 'string') {\n const numericCalories = parseInt(calories.replace(/[^\\d]/g, ''));\n calories = isNaN(numericCalories) ? 0 : numericCalories;\n }\n \n // 有効なデータのみ追加\n if (dishName !== 'Unknown' && calories > 0) {\n menuItems.push({\n dishName: dishName,\n calories: calories\n });\n }\n }\n });\n \n } catch (parseError) {\n console.log('JSON解析エラー:', parseError.message);\n // 手動でデータを抽出を試行\n const manualExtract = extractDataManually(text);\n if (manualExtract) {\n menuItems.push(manualExtract);\n }\n }\n } else {\n // 手動でデータを抽出を試行\n const manualExtract = extractDataManually(text);\n if (manualExtract) {\n menuItems.push(manualExtract);\n }\n }\n \n } catch (error) {\n console.log('データ抽出エラー:', error.message);\n }\n \n return menuItems;\n}\n\n// 手動でデータを抽出する関数\nfunction extractDataManually(text) {\n try {\n const dishMatch = text.match(/\"dishName\"\\s*:\\s*\"([^\"]+)\"/i) || \n text.match(/\"dish_name\"\\s*:\\s*\"([^\"]+)\"/i) ||\n text.match(/\"name\"\\s*:\\s*\"([^\"]+)\"/i);\n \n const caloriesMatch = text.match(/\"calories\"\\s*:\\s*\"?(\\d+)\"?/i) ||\n text.match(/\"calorie\"\\s*:\\s*\"?(\\d+)\"?/i) ||\n text.match(/\"cal\"\\s*:\\s*\"?(\\d+)\"?/i);\n \n if (dishMatch && caloriesMatch) {\n const calories = parseInt(caloriesMatch[1]);\n if (!isNaN(calories) && calories > 0) {\n return {\n dishName: dishMatch[1],\n calories: calories\n };\n }\n }\n } catch (error) {\n console.log('手動抽出エラー:', error.message);\n }\n return null;\n}\n\n// LINEメッセージを生成する関数\nfunction generateLineMessage(menuItems) {\n if (!menuItems || menuItems.length === 0) {\n return \"画像から食品を検出できませんでした。\";\n }\n \n let message = \"カロリー計算:\\n\";\n \n // 各メニューアイテムを追加\n menuItems.forEach((item) => {\n message += `・${item.dishName}(${item.calories}kcal)\\n`;\n });\n \n message += \"シートに記入しました\";\n \n return message;\n}\n\n// 結果が空の場合のデフォルト処理\nif (results.length === 0) {\n console.log('処理可能なデータが見つかりませんでした');\n results.push({\n json: {\n message: \"画像の処理でエラーが発生しました。もう一度お試しください。\",\n menuCount: 0,\n totalCalories: 0,\n timestamp: new Date().toISOString()\n }\n });\n}\n\nconsole.log(`LINE メッセージ生成完了: ${results.length} 件のメッセージを生成しました`);\nreturn results;"
},
"typeVersion": 2
},
{
"id": "56bfb625-6b6b-480d-a81d-55ad8a629c57",
"name": "LINE webhook",
"type": "n8n-nodes-base.webhook",
"position": [
-1040,
144
],
"webhookId": "0980b700-284e-4e52-a33e-71e087eea37f",
"parameters": {
"path": "0980b700-284e-4e52-a33e-71e087eea37f",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 2
},
{
"id": "9e59d336-a880-42aa-b69c-66b445208d1c",
"name": "用户验证",
"type": "n8n-nodes-base.if",
"position": [
-800,
144
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "28c9bc55-ef1b-4fee-8c22-a48b88a82c34",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.body.events[0].source.userId }}",
"rightValue": "{your id}"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "11ddcfb0-a2e8-4002-ba64-bff77a4bf066",
"name": "图片下载",
"type": "n8n-nodes-base.httpRequest",
"position": [
-368,
272
],
"parameters": {
"url": "=https://api-data.line.me/v2/bot/message/{{ $json.body.events[0].message.id }}/content",
"options": {},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer {channel access toaken}"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "b40c936c-5273-493a-822f-36b44de906b3",
"name": "仅消息",
"type": "n8n-nodes-base.set",
"position": [
-128,
-160
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "8504cdbe-9904-4e83-aee9-362f02a25014",
"name": "text",
"type": "string",
"value": "={{ $json.body.events[0].message.text }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "599b110f-7771-4497-a41f-b231c3ebc3b8",
"name": "发送 LINE",
"type": "n8n-nodes-base.httpRequest",
"position": [
1184,
128
],
"parameters": {
"url": "https://api.line.me/v2/bot/message/reply",
"method": "POST",
"options": {},
"jsonBody": "={\n \"replyToken\": \"{{ $('LINE webhook').item.json.body.events[0].replyToken }}\",\n \"messages\": [\n {\n \"type\": \"text\",\n \"text\":{{ JSON.stringify($json.output) }}\n }\n ]\n} ",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer +pLP8YfaojvZ8MzTsryZHngxknOchb4z7RDnDKzh+n2QLxlZKm36+S2yc0WRNrNztHO98iNh1wa+4Vlo73PuRwIrK7q15L493jCEEbRiyv4OKzmHI5hX9PCssHyD9LRZlTdlDfF6M3Vg9Vs1zfAkRgdB04t89/1O/w1cDnyilFU="
},
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "978b63a0-fab0-445f-8f1b-0ab3b92f22b1",
"name": "便签",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1504,
-64
],
"parameters": {
"width": 368,
"height": 560,
"content": "## LINE 食物图片卡路里记录器到 Google Sheets"
},
"typeVersion": 1
},
{
"id": "78855553-f504-4ee0-913e-1b1c933f0cae",
"name": "便签1",
"type": "n8n-nodes-base.stickyNote",
"position": [
240,
192
],
"parameters": {
"color": 4,
"width": 704,
"height": 272,
"content": "## 发送消息到 LINE"
},
"typeVersion": 1
},
{
"id": "e2180426-a161-4483-a630-63eb54cf0d29",
"name": "便签 2",
"type": "n8n-nodes-base.stickyNote",
"position": [
240,
512
],
"parameters": {
"color": 3,
"width": 704,
"height": 272,
"content": "## 写入 Google Sheets"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "a7eb22fe-627c-4d1a-aaee-a05a9fb4eb81",
"connections": {
"Code": {
"main": [
[
{
"node": "Append row in sheet",
"type": "main",
"index": 0
}
]
]
},
"Code1": {
"main": [
[
{
"node": "Edit Fields1",
"type": "main",
"index": 0
}
]
]
},
"Switch": {
"main": [
[
{
"node": "only message",
"type": "main",
"index": 0
}
],
[
{
"node": "images download",
"type": "main",
"index": 0
}
]
]
},
"AI Agent": {
"main": [
[
{
"node": "send LINE",
"type": "main",
"index": 0
}
]
]
},
"Edit Fields1": {
"main": [
[
{
"node": "send LINE",
"type": "main",
"index": 0
}
]
]
},
"LINE webhook": {
"main": [
[
{
"node": "user verification",
"type": "main",
"index": 0
}
]
]
},
"only message": {
"main": [
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
]
]
},
"Analyze image": {
"main": [
[
{
"node": "Code",
"type": "main",
"index": 0
},
{
"node": "Code1",
"type": "main",
"index": 0
}
]
]
},
"Simple Memory": {
"ai_memory": [
[
{
"node": "AI Agent",
"type": "ai_memory",
"index": 0
}
]
]
},
"images download": {
"main": [
[
{
"node": "Analyze image",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"user verification": {
"main": [
[
{
"node": "Switch",
"type": "main",
"index": 0
}
]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
高级 - 个人效率, 多模态 AI
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
导出_dian-memo_03
AI语音与文本笔记 - 集成LINE消息、Supabase向量数据库和Gmail
If
Set
Code
+14
30 节点kote2
AI RAG 检索增强
每日WhatsApp摘要与群组级别控制
WhatsApp群组摘要工作流
If
Set
Code
+13
39 节点Luís Philipe Trindade
个人效率
批量SEO内容生成与带AI图片的Webflow草稿创建(模板)
使用GPT、Gemini图片和Webflow草稿创建进行批量SEO内容生成
If
Set
Code
+18
54 节点Dahiana
内容创作
基于 YouTube 视频的自主博客发布
使用 ChatGPT、Sheets、Apify、Pexels 和 WordPress 从 YouTube 视频自主发布博客
If
Set
Code
+18
80 节点Oriol Seguí
内容创作
使用GPT-5 nano和Google Sheets抓取网站并回答问题
使用GPT-5 nano和Google Sheets抓取网站并回答问题
If
Set
Xml
+17
44 节点Oriol Seguí
市场调研
1. 播放列表详情设置机器人副本
使用 Suno、GPT-4、Runway 和 Creatomate 创建 AI 生成的 YouTube 音乐播放列表
If
Set
Code
+22
203 节点Joseph
内容创作
工作流信息
难度等级
高级
节点数量17
分类2
节点类型12
作者
kote2
@kote2I share practical examples and ideas for AI automation using tools like n8n, explained in a way that’s easy for beginners to understand. While Dify is currently more well-known in Japan, n8n complements it and is expected to gain even more attention in the future. This channel aims to be a practical guide you can rely on when that wave of popularity arrives. That said, I’m still learning too—so let’s learn and grow together!
外部链接
在 n8n.io 查看 →
分享此工作流