多模态费用追踪:Telegram、Gemini AI 与 Google Sheets
高级
这是一个Personal Productivity, AI Chatbot领域的自动化工作流,包含 25 个节点。主要使用 If, Set, Switch, SplitOut, Telegram 等节点。 使用 Telegram、Gemini AI 和 Google Sheets 的多模态费用追踪系统
前置要求
- •Telegram Bot Token
- •Google Sheets API 凭证
- •Google Gemini API Key
使用的节点 (25)
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"meta": {
"instanceId": "e4f10bef48753951b827b1628c136c25720855dd405c916d09e788211699198e",
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "7be734f2-0de6-4763-81e5-346cb715bd66",
"name": "便签",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1664,
624
],
"parameters": {
"width": 896,
"height": 928,
"content": "# 🚀 快速入门"
},
"typeVersion": 1
},
{
"id": "dba88ead-1ca9-488d-9cb2-c1fdc4156dce",
"name": "便签1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-688,
560
],
"parameters": {
"color": 2,
"width": 672,
"height": 992,
"content": "## 1) 消息接收与路由"
},
"typeVersion": 1
},
{
"id": "67cb65eb-65c3-4e83-a5db-8fc0a227513a",
"name": "便签2",
"type": "n8n-nodes-base.stickyNote",
"position": [
0,
560
],
"parameters": {
"color": 3,
"width": 688,
"height": 992,
"content": "## 2) 输入捕获与标准化"
},
"typeVersion": 1
},
{
"id": "bbcaf572-fe02-49d9-bb73-9e0229c4e931",
"name": "便签3",
"type": "n8n-nodes-base.stickyNote",
"position": [
720,
560
],
"parameters": {
"color": 5,
"width": 432,
"height": 992,
"content": "## 3) 支出解析与验证"
},
"typeVersion": 1
},
{
"id": "40c74ab6-4079-475d-89d1-c861ca778c94",
"name": "便签4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1168,
560
],
"parameters": {
"color": 4,
"width": 1056,
"height": 992,
"content": "## 4) 行生成、表格写入与确认"
},
"typeVersion": 1
},
{
"id": "5ca4b51a-2d7e-46f9-82a5-081b0cb970fd",
"name": "GSheet: Log Expense",
"type": "n8n-nodes-base.googleSheets",
"position": [
1824,
1056
],
"parameters": {
"columns": {
"value": {},
"schema": [
{
"id": "output",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "output",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "autoMapInputData",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {
"cellFormat": "RAW"
},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 161899167,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1GRwglX459qYYAQm_gRZadyDwVR1dw8t6zuZU3T-T-Ak/edit#gid=161899167",
"cachedResultName": "test"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1GRwglX459qYYAQm_gRZadyDwVR1dw8t6zuZU3T-T-Ak",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1GRwglX459qYYAQm_gRZadyDwVR1dw8t6zuZU3T-T-Ak/edit?usp=drivesdk",
"cachedResultName": "记账"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "i2QQ5h70aiZ7H0s3",
"name": "Google Sheets(owen)"
}
},
"retryOnFail": true,
"typeVersion": 4.7
},
{
"id": "297ff453-2268-40ba-95c3-fa7a3e736467",
"name": "LLM: Gemini Flash",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
768,
1408
],
"parameters": {
"options": {}
},
"credentials": {
"googlePalmApi": {
"id": "Kgz5ypv084tCLfvw",
"name": "Gemini (wudi)"
}
},
"typeVersion": 1
},
{
"id": "9519104e-7bb0-4b48-aa2c-cd416266a9de",
"name": "Gemini:转录语音",
"type": "@n8n/n8n-nodes-langchain.googleGemini",
"position": [
272,
1072
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "models/gemini-2.5-flash",
"cachedResultName": "models/gemini-2.5-flash"
},
"options": {},
"resource": "audio",
"inputType": "binary",
"binaryPropertyName": "=data "
},
"credentials": {
"googlePalmApi": {
"id": "Kgz5ypv084tCLfvw",
"name": "Gemini (wudi)"
}
},
"retryOnFail": true,
"typeVersion": 1
},
{
"id": "8bd5377e-39ef-4af7-846d-1d3a279151c2",
"name": "Telegram: Send Confirmation",
"type": "n8n-nodes-base.telegram",
"position": [
2016,
1056
],
"webhookId": "94947e31-c3ff-4888-bdc6-946478134923",
"parameters": {
"text": "={{\n(() => {\n const items = $input.all();\n\n const arr = items\n .map(i => i.json?.output ?? i.json)\n .filter(Boolean);\n\n const lines = arr.map(e => {\n const item = (e?.Item ?? '').toString().trim() || '—';\n const amount = (e?.Amount ?? '').toString().trim() || '—';\n const date = e?.Date ? ` (${e.Date})` : '';\n return `• ${item} — ${amount}${date}`;\n });\n\n const text =\n '📒 Bookkeeping Complete\\n\\n' +\n (lines.length ? lines.join('\\n') : '(No items found)');\n\n // Telegram MarkdownV2 需要转义的字符:\n // _ * [ ] ( ) ~ ` > # + - = | { } . ! \\\n const escapeMdV2 = (s) =>\n s.replace(/([_*[\\]()~`>#+\\-=|{}.!\\\\])/g, '\\\\$1');\n\n return escapeMdV2(text);\n})()\n}}\n",
"chatId": "<Your chat id>",
"additionalFields": {
"parse_mode": "MarkdownV2"
}
},
"credentials": {
"telegramApi": {
"id": "GqenigS1DQQpGb6b",
"name": "Telegram (owenperosonal)"
}
},
"executeOnce": true,
"retryOnFail": true,
"typeVersion": 1.2,
"waitBetweenTries": 3000
},
{
"id": "ec454606-5cc7-45ff-a8fe-a8ecd39b7b13",
"name": "Telegram: Get Voice File",
"type": "n8n-nodes-base.telegram",
"position": [
64,
1072
],
"webhookId": "61b155dd-389b-4673-996a-2bce72c9a6f7",
"parameters": {
"fileId": "={{ $json.message.voice.file_id }}",
"resource": "file",
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"id": "GqenigS1DQQpGb6b",
"name": "Telegram (owenperosonal)"
}
},
"retryOnFail": true,
"typeVersion": 1.2
},
{
"id": "ab30a0a4-0f88-437a-b75f-488eb11eb38b",
"name": "Set: Text Input",
"type": "n8n-nodes-base.set",
"position": [
384,
912
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "bed1c3bb-9ee7-4663-b89a-8a701df2c049",
"name": "raw_text",
"type": "string",
"value": "={{ $json.message.text }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "9850615f-f28d-4b68-8fe2-fbf704172667",
"name": "Set: Voice Input (Text)",
"type": "n8n-nodes-base.set",
"position": [
496,
1072
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "82a0d6b4-f320-4b39-b05a-a2723f4d22fa",
"name": "raw_text",
"type": "string",
"value": "={{ $json.content.parts.toJsonString() }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "8cbe3328-cdd1-4773-90ad-4822859ddba1",
"name": "AI: Extract Expenses",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
832,
1040
],
"parameters": {
"text": "=information:{{ $json.raw_text }}",
"options": {
"systemMessage": "=You are a STRICT, deterministic expense parser. The user will provide free-form text or an ASR (voice) transcription that describes one or more bookkeeping entries.\n\nGOAL\nReturn a JSON ARRAY of 0..N objects. Each object has these EXACT keys:\n{\n \"amount\": number | null, // numeric value only; no currency symbol\n \"item\": string | null, // what was paid for / received\n \"date\": date // ISO 8601 \"YYYY-MM-DD\"; \n\nCURRENT DATE CONTEXT (REQUIRED)\n- NOW_ISO = \"{{ new Date }}\" \n- Define CURRENT_DATE as the calendar date of NOW_ISO (YYYY-MM-DD) respecting its timezone info if present.\n\nHARD RULES (NO HALLUCINATIONS)\n- Work ONLY with the given input text; DO NOT invent, infer, or fetch anything external.\n- If a field cannot be reliably determined, set it to null (do NOT guess). Exception: \"date\" must never be null—if no explicit/relative date is found, use CURRENT_DATE.\n- Output MUST be raw JSON array only (no markdown, no comments, no extra text).\n- Each distinct purchase must yield its own object. Do NOT merge separate purchases. Do NOT compute totals from line items unless the text explicitly marks a “total”.\n- Amounts are positive numbers; do NOT add signs to indicate expense/income.\n\nMULTI-ENTRY DETECTION\nTreat as separate purchases when the text clearly presents distinct (amount, item) pairs or clearly separated entries by:\n- Newlines, bullet points, semicolons/commas that separate complete (amount + item) phrases, or connectors like “and/&, plus” when each part has its own amount or distinct item.\n- Examples of separate entries:\n - \"Lunch 12; Grab 18; Netflix 55\" → three objects.\n - \"RM8 coffee, RM5 bun\" → two objects.\nNOT separate (single entry):\n - A list of items but ONE explicit \"total\" (e.g., \"apples 3, milk 5, total 8\") → output ONE object with amount=8 and item=apples & milk.\n - Quantity/price math for the same item (e.g., \"2 x coffee RM5 each, total RM10\") → ONE object, amount=10, item=\"coffee\".\nIf multiple amounts exist but items are not clearly distinguishable, create multiple objects with item=null rather than guessing item names.\n\nAMOUNT PARSING\n- Normalize to a JSON number (strip currency symbols/codes/words): RM12.50 → 12.5, $1,299 → 1299, MYR 36 → 36.\n- Support magnitude suffixes: 1.2k/1.2K → 1200; 36k/36K → 36000.\n- Prefer an explicit total; if both unit price and total appear for the same purchase, choose the total.\n- Ignore percentages unless explicitly stated as the paid amount.\n- If multiple numeric candidates exist within one purchase with no clear total, choose the first well-formed currency-like amount; otherwise amount = null.\n\nITEM EXTRACTION\n- Concise description of what the payment is for (e.g., \"coffee\", \"Grab ride\", \"rental\", \"Netflix subscription\").\n- Remove ASR fillers (“uh”, “you know”), keep core item only.\n- If truly unknown, item = null.\n\nDATE RESOLUTION\n- Always output ISO \"YYYY-MM-DD\".\n- Recognize explicit dates in common formats and normalize (e.g., 22/10/2025, 2025-10-22, Oct 22, 2025). If month/day are given without a year and it is unambiguous, fill the year from CURRENT_DATE; otherwise treat missing parts as absent and use CURRENT_DATE.\n- Relative terms (multi-language; case-insensitive):\n - \"today\", \"今天\", \"hari ini\" → CURRENT_DATE\n - \"yesterday\", \"昨天\", \"semalam\" → CURRENT_DATE minus 1 day\n - \"tomorrow\", \"明天\", \"esok\" → CURRENT_DATE plus 1 day\n - \"the day before yesterday\" / \"前天\" → CURRENT_DATE minus 2 days\n- If a single relative date clearly applies to the whole input, apply it to all entries. If different parts contain different explicit/relative dates, resolve per entry. If no date cue for an entry, use CURRENT_DATE.\n\nNORMALIZATION & SANITY\n- Trim whitespace; tolerate ASR noise and mixed punctuation (including full-width).\n- Do not include currency symbols/codes anywhere in JSON.\n\nOUTPUT FORMAT\n- Return exactly one JSON array. Each array element is an object with keys in this order: amount, item, date.\n- Numbers must be valid JSON numbers (no quotes).\n\nEXAMPLES (assume NOW_ISO = \"2025-10-22T15:00:00+08:00\", so CURRENT_DATE = \"2025-10-22\")\n\nInput: \"Paid RM12.50 for latte at Starbucks today\"\nOutput:\n[{\"amount\":12.5,\"item\":\"latte at Starbucks\",\"date\":\"2025-10-22\"}]\n\nInput: \"Grab ride to Mid Valley, 18 ringgit, yesterday; Netflix monthly 55\"\nOutput:\n[\n {\"amount\":18,\"item\":\"Grab ride to Mid Valley\",\"date\":\"2025-10-21\"},\n {\"amount\":55,\"item\":\"Netflix monthly\",\"date\":\"2025-10-22\"}\n]\n\nInput: \"RM8 coffee, RM5 bun\"\nOutput:\n[\n {\"amount\":8,\"item\":\"coffee\",\"date\":\"2025-10-22\"},\n {\"amount\":5,\"item\":\"bun\",\"date\":\"2025-10-22\"}\n]\n\nInput: \"apples 3, milk 5, TOTAL 8\"\nOutput:\n[{\"amount\":8,\"item\":\"apples & milk\",\"date\":\"2025-10-22\"}]\n"
},
"promptType": "define",
"hasOutputParser": true
},
"retryOnFail": true,
"typeVersion": 2.2
},
{
"id": "cd20d803-47a3-496b-8160-0052c6b50ef4",
"name": "Split: Entries to Rows",
"type": "n8n-nodes-base.splitOut",
"position": [
1216,
1040
],
"parameters": {
"include": "allOtherFields",
"options": {},
"fieldToSplitOut": "output"
},
"executeOnce": false,
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "a1e5d645-da07-479c-84c7-5e6ad67d2f7c",
"name": "Telegram: Send error message",
"type": "n8n-nodes-base.telegram",
"position": [
-144,
1392
],
"webhookId": "94947e31-c3ff-4888-bdc6-946478134923",
"parameters": {
"text": "=🤖Sorry, I can only understand text, voice and image for bookkeeping. ",
"chatId": "<Your chat id>",
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"id": "GqenigS1DQQpGb6b",
"name": "Telegram (owenperosonal)"
}
},
"executeOnce": true,
"retryOnFail": true,
"typeVersion": 1.2
},
{
"id": "076077d4-a0c9-4800-aa1e-1f455255a8db",
"name": "Gemini: Analyze an image",
"type": "@n8n/n8n-nodes-langchain.googleGemini",
"position": [
272,
1264
],
"parameters": {
"text": "=Financial Image Text Extraction Prompt\n\nYour task is to analyze the provided image and **extract all text and numerical information related to financial or transactional data**. \nThe image may contain receipts, invoices, transfer records, expense summaries, or digital payment screenshots (e.g., WeChat, Alipay, banking apps).\n\n#### Instructions:\n- Extract **all visible text and numbers**, including:\n - Dates and times \n - Merchant or transaction party names \n - Notes, descriptions, or remarks \n - Amounts, currency symbols, and positive/negative signs \n - Summary information (e.g., total income, total expense)\n- **Preserve the original order and wording** as they appear in the image. \n- Ensure numerical accuracy and retain all currency symbols. \n- **Ignore decorative or non-informational elements**, such as logos, icons, watermarks, background graphics, or design borders. \n- Do **not** interpret, categorize, or restructure the extracted data. \n The output should be **raw readable text** that captures all relevant words and numbers for bookkeeping analysis.\n\n#### Goal:\nProduce an **accurate, unmodified textual extraction** of the financial and accounting information visible in the image — ready for further processing by a bookkeeping or accounting system.\n",
"modelId": {
"__rl": true,
"mode": "list",
"value": "models/gemini-2.5-flash",
"cachedResultName": "models/gemini-2.5-flash"
},
"options": {},
"resource": "image",
"inputType": "binary",
"operation": "analyze"
},
"credentials": {
"googlePalmApi": {
"id": "OBsJ1xTy5eLJvjhJ",
"name": "Gemini(pixel)"
}
},
"retryOnFail": true,
"typeVersion": 1
},
{
"id": "fe77a802-f56e-4fae-ae7c-0c6dabf43d2c",
"name": "Set: image Input (Text)",
"type": "n8n-nodes-base.set",
"position": [
496,
1264
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "82a0d6b4-f320-4b39-b05a-a2723f4d22fa",
"name": "raw_text",
"type": "string",
"value": "={{ $json.content.parts.toJsonString() }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "3c907845-b556-4a13-a93b-1319e953e001",
"name": "Route: Text, Voice or Image?",
"type": "n8n-nodes-base.switch",
"position": [
-384,
1136
],
"parameters": {
"rules": {
"values": [
{
"outputKey": "Text",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "a3e1bf10-5e6d-4004-87f9-b0f6e8c421c8",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ !!$json.message.text }}",
"rightValue": "text"
}
]
},
"renameOutput": true
},
{
"outputKey": "Voice",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "7de0d37c-e95d-4780-958b-25fe7a851243",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ !!$json.message.voice }}",
"rightValue": "voice"
}
]
},
"renameOutput": true
},
{
"outputKey": "Image",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "f85ee560-74b1-47ab-ac61-06081de1a14f",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ !!$json.message.photo }}",
"rightValue": "photo"
}
]
},
"renameOutput": true
}
]
},
"options": {
"fallbackOutput": "extra",
"allMatchingOutputs": false,
"renameFallbackOutput": "else"
}
},
"typeVersion": 3.3
},
{
"id": "45416109-6e88-4b09-8327-bea0d9878b7e",
"name": "Auto-Fix JSON",
"type": "@n8n/n8n-nodes-langchain.outputParserAutofixing",
"position": [
880,
1248
],
"parameters": {
"options": {
"prompt": "Instructions:\n--------------\n{instructions}\n--------------\nCompletion:\n--------------\n{completion}\n--------------\n\nAbove, the Completion did not satisfy the constraints given in the Instructions.\nError:\n--------------\n{error}\n--------------\n\nPlease try again. Please only respond with an answer that satisfies the constraints laid out in the Instructions:"
}
},
"typeVersion": 1
},
{
"id": "6c8d0ca0-9e88-41d7-9692-32b3751c70b0",
"name": "AI Helper: Define Schema",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
992,
1392
],
"parameters": {
"jsonSchemaExample": "[\n {\n \"amount\": \"number | null\",\n \"item\": \"string | null\", \n \"date\": \"date\"\n }\n]"
},
"typeVersion": 1.3
},
{
"id": "95435178-b029-4319-a886-7a0aef028363",
"name": "Telegram: Get Image File",
"type": "n8n-nodes-base.telegram",
"position": [
64,
1264
],
"webhookId": "61b155dd-389b-4673-996a-2bce72c9a6f7",
"parameters": {
"fileId": "={{ $json.message.photo[0].file_id }}",
"resource": "file",
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"id": "GqenigS1DQQpGb6b",
"name": "Telegram (owenperosonal)"
}
},
"retryOnFail": true,
"typeVersion": 1.2
},
{
"id": "a0d74a66-0e2f-460a-ada8-c52c1a38535b",
"name": "Start: On Telegram Message",
"type": "n8n-nodes-base.telegramTrigger",
"position": [
-608,
1168
],
"webhookId": "ae9666ea-0aaa-4b17-88ae-9049e0dd1213",
"parameters": {
"updates": [
"message"
],
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"id": "GqenigS1DQQpGb6b",
"name": "Telegram (owenperosonal)"
}
},
"typeVersion": 1.2
},
{
"id": "44724e36-7f53-4e42-b588-c7a808f57f70",
"name": "Set: Extract Output",
"type": "n8n-nodes-base.set",
"position": [
1632,
1056
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "6b917f33-f6c0-4a49-b12c-6861238874b6",
"name": "Amount",
"type": "string",
"value": "={{ $json.output.amount }}"
},
{
"id": "f029fc1b-937a-432c-9832-fa1a0b7717ed",
"name": "Item",
"type": "string",
"value": "={{ $json.output.item }}"
},
{
"id": "e7908c7b-e1a5-4854-b6d2-7a57d90521b6",
"name": "Date",
"type": "string",
"value": "={{ $json.output.date }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "b2122f43-7eaf-4d09-ba73-b756fa8d2863",
"name": "If null?",
"type": "n8n-nodes-base.if",
"position": [
1424,
1152
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "or",
"conditions": [
{
"id": "2afe62ea-0a1b-4836-a1d4-7863e35e7f39",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ !!$json.output }}",
"rightValue": ""
},
{
"id": "c8509d26-8c3c-4e43-8870-47691e631d8d",
"operator": {
"type": "array",
"operation": "contains",
"rightType": "any"
},
"leftValue": "={{ $json.output }}",
"rightValue": "null"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "b4d6dc9a-d623-455d-8fd5-a2f757229a07",
"name": "Telegram: Send Null",
"type": "n8n-nodes-base.telegram",
"position": [
1616,
1280
],
"webhookId": "94947e31-c3ff-4888-bdc6-946478134923",
"parameters": {
"text": "=📒 Bookkeeping Complete\n\nnull",
"chatId": "<Your chat id>",
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"id": "GqenigS1DQQpGb6b",
"name": "Telegram (owenperosonal)"
}
},
"executeOnce": true,
"retryOnFail": true,
"typeVersion": 1.2
}
],
"pinData": {},
"connections": {
"If null?": {
"main": [
[
{
"node": "Set: Extract Output",
"type": "main",
"index": 0
}
],
[
{
"node": "Telegram: Send Null",
"type": "main",
"index": 0
}
]
]
},
"Auto-Fix JSON": {
"ai_outputParser": [
[
{
"node": "AI: Extract Expenses",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"Set: Text Input": {
"main": [
[
{
"node": "AI: Extract Expenses",
"type": "main",
"index": 0
}
]
]
},
"LLM: Gemini Flash": {
"ai_languageModel": [
[
{
"node": "Auto-Fix JSON",
"type": "ai_languageModel",
"index": 0
},
{
"node": "AI: Extract Expenses",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"GSheet: Log Expense": {
"main": [
[
{
"node": "Telegram: Send Confirmation",
"type": "main",
"index": 0
}
]
]
},
"Set: Extract Output": {
"main": [
[
{
"node": "GSheet: Log Expense",
"type": "main",
"index": 0
}
]
]
},
"AI: Extract Expenses": {
"main": [
[
{
"node": "Split: Entries to Rows",
"type": "main",
"index": 0
}
]
]
},
"Split: Entries to Rows": {
"main": [
[
{
"node": "If null?",
"type": "main",
"index": 0
}
]
]
},
"Set: Voice Input (Text)": {
"main": [
[
{
"node": "AI: Extract Expenses",
"type": "main",
"index": 0
}
]
]
},
"Set: image Input (Text)": {
"main": [
[
{
"node": "AI: Extract Expenses",
"type": "main",
"index": 0
}
]
]
},
"AI Helper: Define Schema": {
"ai_outputParser": [
[
{
"node": "Auto-Fix JSON",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"Gemini: Analyze an image": {
"main": [
[
{
"node": "Set: image Input (Text)",
"type": "main",
"index": 0
}
]
]
},
"Gemini: Transcribe Voice": {
"main": [
[
{
"node": "Set: Voice Input (Text)",
"type": "main",
"index": 0
}
]
]
},
"Telegram: Get Image File": {
"main": [
[
{
"node": "Gemini: Analyze an image",
"type": "main",
"index": 0
}
]
]
},
"Telegram: Get Voice File": {
"main": [
[
{
"node": "Gemini: Transcribe Voice",
"type": "main",
"index": 0
}
]
]
},
"Start: On Telegram Message": {
"main": [
[
{
"node": "Route: Text, Voice or Image?",
"type": "main",
"index": 0
}
]
]
},
"Route: Text, Voice or Image?": {
"main": [
[
{
"node": "Set: Text Input",
"type": "main",
"index": 0
}
],
[
{
"node": "Telegram: Get Voice File",
"type": "main",
"index": 0
}
],
[
{
"node": "Telegram: Get Image File",
"type": "main",
"index": 0
}
],
[
{
"node": "Telegram: Send error message",
"type": "main",
"index": 0
}
]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
高级 - 个人效率, AI 聊天机器人
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
宠物美容发布与预约自动化
使用AI、Facebook和Telegram机器人自动化宠物美容发布与预约
If
Set
Switch
+17
36 节点Christian Moises
AI 聊天机器人
使用Gemini、语音和图像生成构建多模态Telegram AI助手
使用Gemini、语音和图像生成构建多模态Telegram AI助手
If
Set
Code
+19
95 节点Iniyavan JC
个人效率
营养追踪与饮食记录(Telegram、Gemini AI和Google Sheets)
营养追踪与饮食记录(Telegram、Gemini AI和Google Sheets)
If
Set
Code
+13
55 节点John Alejandro SIlva
AI 聊天机器人
ESPOLBot日历|常见问题
基于Telegram、MongoDB和Gemini AI的大学常见问题与日历助手
Set
Code
Html
+14
91 节点Club de Inteligencia Artificial Politécnico CIAP
客服机器人
TG-Bot-AI-日历-v1-数据库-代理
通过Telegram使用Gemini AI助手管理Google日历事件
If
Set
Switch
+7
16 节点Andrew
个人效率
个人 Telegram AI 助手机器人
语音与文本助手,集成Telegram、Gemini AI、日历、Gmail和Notion
If
Switch
Telegram
+9
17 节点Paul Abraham
个人效率