预测话语结束以实现更流畅的Telegram和Gemini AI代理聊天
高级
这是一个Support, AI领域的自动化工作流,包含 29 个节点。主要使用 If, Set, Wait, Redis, Telegram 等节点,结合人工智能技术实现智能自动化。 预测话语结束以实现更流畅的Telegram和Gemini AI代理聊天
前置要求
- •Redis 服务器连接信息
- •Telegram Bot Token
- •可能需要目标 API 的认证凭证
- •Google Gemini API Key
使用的节点 (29)
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"meta": {
"instanceId": "408f9fb9940c3cb18ffdef0e0150fe342d6e655c3a9fac21f0f644e8bedabcd9",
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "dd511e76-27a0-47a1-b475-d00fffa22eb8",
"name": "Telegram Trigger",
"type": "n8n-nodes-base.telegramTrigger",
"position": [
-1280,
120
],
"webhookId": "dce8f9a4-86d1-4dd9-a83a-4de75185ae21",
"parameters": {
"updates": [
"message"
],
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"id": "Lk9x8q4NhLDMjfTV",
"name": "jimleuk_bot"
}
},
"typeVersion": 1.2
},
{
"id": "fef3c7b6-ac57-4b83-8f21-2babd81d3b50",
"name": "AI Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
1280,
320
],
"parameters": {
"text": "={{\n$('Session Ref').first().json.data.messages?.parseJson()\n .map(msg => msg.value)\n .join(' ')\n}}",
"options": {
"systemMessage": "Do not format your response in markdown, use plain text instead."
},
"promptType": "define"
},
"typeVersion": 2
},
{
"id": "084bfb67-c59b-44c4-a310-4c25743cd8f9",
"name": "Google Gemini Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
1260,
520
],
"parameters": {
"options": {},
"modelName": "models/gemini-2.5-flash-preview-05-20"
},
"credentials": {
"googlePalmApi": {
"id": "dSxo6ns5wn658r8N",
"name": "Google Gemini(PaLM) Api account"
}
},
"typeVersion": 1
},
{
"id": "4733b8d3-427d-4724-a5a3-7eb787941494",
"name": "Redis Chat Memory",
"type": "@n8n/n8n-nodes-langchain.memoryRedisChat",
"position": [
1420,
520
],
"parameters": {
"sessionKey": "=session/{{ $('Session Ref').first().json.data.from }}/agent",
"sessionIdType": "customKey",
"contextWindowLength": 10
},
"credentials": {
"redis": {
"id": "zU4DA70qSDrZM1El",
"name": "Redis account (localhost)"
}
},
"typeVersion": 1.5
},
{
"id": "8f7e6148-b1a5-46b5-934a-0c75f20898d8",
"name": "获取值",
"type": "n8n-nodes-base.set",
"position": [
-860,
120
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "7cee3033-0615-43ac-93fd-5397c759e6a3",
"name": "from",
"type": "string",
"value": "={{ $json.message.chat.id }}"
},
{
"id": "c2bb1875-7074-411f-a14a-42c699e5bdc1",
"name": "message",
"type": "string",
"value": "={{ $json.message.text }}"
},
{
"id": "34d5087e-79be-4181-b839-0a55b95133e8",
"name": "createdAt",
"type": "string",
"value": "={{ $now.toISO() }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "52cc0bd2-bb0a-4c2c-a1a5-2a9104d891da",
"name": "更新会话",
"type": "n8n-nodes-base.redis",
"position": [
-920,
700
],
"parameters": {
"key": "=session/{{ $('Prediction Subworkflow').item.json.from }}",
"value": "={{\n{\n ...($('Get Session').item.json.data ?? {}),\n messages: [\n ...($('Get Session').item.json.data?.messages\n ? $('Get Session').item.json.data?.messages.parseJson()\n : []\n ),\n {\n value: $('Prediction Subworkflow').item.json.message,\n createdAt: $('Prediction Subworkflow').item.json.createdAt\n }\n ].toJsonString(),\n from: $('Prediction Subworkflow').item.json.from\n}\n}}",
"expire": true,
"keyType": "hash",
"operation": "set"
},
"credentials": {
"redis": {
"id": "zU4DA70qSDrZM1El",
"name": "Redis account (localhost)"
}
},
"typeVersion": 1
},
{
"id": "7bdee33c-a2e7-49a3-b782-d045f3f46dd3",
"name": "获取会话",
"type": "n8n-nodes-base.redis",
"position": [
-1100,
700
],
"parameters": {
"key": "=session/{{ $json.from }}",
"keyType": "hash",
"options": {},
"operation": "get",
"propertyName": "data"
},
"credentials": {
"redis": {
"id": "zU4DA70qSDrZM1El",
"name": "Redis account (localhost)"
}
},
"typeVersion": 1
},
{
"id": "0fc0b9eb-3553-4fdb-befc-7d7891305405",
"name": "正在等待?",
"type": "n8n-nodes-base.if",
"position": [
-80,
1020
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "0e37d8ff-3d04-4224-84cc-defa80dc4a8b",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Get Session').item.json.data?.state }}",
"rightValue": "waiting"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "de3eb7bb-81e0-4169-a6f4-286a1ac9a2f7",
"name": "更新会话1",
"type": "n8n-nodes-base.redis",
"position": [
40,
300
],
"parameters": {
"key": "=session/{{ $('Session Ref').first().json.data.from }}",
"value": "={{\n{\n state: 'waiting',\n resumeUrl: $execution.resumeUrl\n}\n}}",
"expire": true,
"keyType": "hash",
"operation": "set"
},
"credentials": {
"redis": {
"id": "zU4DA70qSDrZM1El",
"name": "Redis account (localhost)"
}
},
"typeVersion": 1
},
{
"id": "c7fb3fba-9d6a-4c68-a995-5539ab6bcf63",
"name": "是新会话?",
"type": "n8n-nodes-base.if",
"position": [
-560,
700
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "71db97f1-e5ba-49d1-8a9a-b9df3a989c77",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ !$json.data?.state }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "8bbb222c-d3d1-4c03-931c-37f1d2d37df2",
"name": "Google Gemini Chat Model1",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
300,
460
],
"parameters": {
"options": {},
"modelName": "models/gemini-2.5-flash-lite-preview-06-17"
},
"credentials": {
"googlePalmApi": {
"id": "dSxo6ns5wn658r8N",
"name": "Google Gemini(PaLM) Api account"
}
},
"typeVersion": 1
},
{
"id": "3a285fef-8c80-48dc-8e79-2c30ff9d351c",
"name": "获取会话2",
"type": "n8n-nodes-base.redis",
"position": [
720,
460
],
"parameters": {
"key": "=session/{{ $('Session Ref').first().json.data.from }}",
"keyType": "hash",
"options": {},
"operation": "get",
"propertyName": "data"
},
"credentials": {
"redis": {
"id": "zU4DA70qSDrZM1El",
"name": "Redis account (localhost)"
}
},
"typeVersion": 1
},
{
"id": "e8254612-ff46-4165-ab93-a6c9d7a2c583",
"name": "会话引用",
"type": "n8n-nodes-base.noOp",
"position": [
-120,
300
],
"parameters": {},
"typeVersion": 1
},
{
"id": "bdd227f1-65fd-46d0-8e0c-23e812f83967",
"name": "会话结束?",
"type": "n8n-nodes-base.if",
"position": [
880,
460
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "398277f7-9386-4f99-ab9c-f99fe59c872e",
"operator": {
"type": "object",
"operation": "empty",
"singleValue": true
},
"leftValue": "={{ Object.assign({}, $json.data ?? {}) }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "a9611069-9cf9-4090-aa6e-cc6a3f4a0fa8",
"name": "等待 Webhook",
"type": "n8n-nodes-base.wait",
"position": [
560,
460
],
"webhookId": "d753b11d-0a61-40e5-b1c4-d217e106eaac",
"parameters": {
"resume": "webhook",
"options": {},
"resumeUnit": "seconds",
"resumeAmount": 20,
"limitWaitTime": true
},
"typeVersion": 1.1
},
{
"id": "456d5b81-7eee-49fd-9b27-93e9e8fbe7b8",
"name": "更新会话2",
"type": "n8n-nodes-base.redis",
"position": [
1620,
320
],
"parameters": {
"key": "=session/{{ $('Session Ref').first().json.data.from }}",
"operation": "delete"
},
"credentials": {
"redis": {
"id": "zU4DA70qSDrZM1El",
"name": "Redis account (localhost)"
}
},
"typeVersion": 1
},
{
"id": "d778edf7-4152-4bd9-a720-a0a28db45369",
"name": "是机器人命令?",
"type": "n8n-nodes-base.if",
"position": [
-1080,
120
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "bff0d1a5-1d78-4af6-a643-b2fd28f10fba",
"operator": {
"type": "string",
"operation": "startsWith"
},
"leftValue": "={{ $json.message.text }}",
"rightValue": "/"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "a465cb15-8faf-42fb-b00e-51af15c596da",
"name": "预测话语结束",
"type": "@n8n/n8n-nodes-langchain.textClassifier",
"position": [
200,
300
],
"parameters": {
"options": {
"systemPromptTemplate": "=You are an NLP expert who predicts whether a message is the end of an turn/utterance i.e., whether the user's message is complete or if more parts of the message are likely to follow. Help predict the given message or partial message to determine whether it is now the agent's turn to respond to the user.\n\n## Techniques to use\n* Temporal Threshold (Inactivity Delay) - Use a decay model—each consecutive message shortens the threshold unless punctuation suggests completeness.\n* Punctuation Patterns - Strong indicators of message completeness: Ends with period ., question mark ?, or exclamation mark !. Ends with an emoji or newline after a complete sentence. Weak or uncertain indicators: Ellipsis ... → often implies continuation. Dash - or incomplete sentence → wait for more.\n* Linguistic Features - Lexical cues (last word, punctuation). Part-of-speech tags (is the sentence syntactically complete?). Message length and position in sequence. Semantic cues like discourse markers: \"anyway\", \"so\", \"that's all\"\n* Conversational Cues (Pragmatic Signals) - \"That's it\", \"Done\", \"Hope that helps\", \"Thanks\" → End markers. \"Let me continue\", \"Hold on\", \"Part 2\" → Continuation markers.\n\n### Sample Dataset\nLabel: 1 = end of utterance, 0 = continuation\n* \"Here's the plan for tomorrow.\" = 1,\n* \"First, we meet at 9am.\" = 0,\n* \"Then we head to the venue\" = 0,\n* \"...and set everything up.\" = 0,\n* \"Let me know if you're free!\" = 1,\n* \"Part 1 of the idea is this\" = 0,\n* \"More to come\" = 0,\n* \"That's all!\" = 1,\n* \"Thanks!\" = 1\n* \"Next, we should discuss logistics\" = 0"
},
"inputText": "={{\n$('Session Ref').item.json.data.messages.parseJson()\n .map(msg => `[${msg.createdAt}] ${msg.value}`)\n .join(' ')\n}}",
"categories": {
"categories": [
{
"category": "end_of_utterance",
"description": "The user has reached their end of turn or end of utterance"
},
{
"category": "has_more_to_follow",
"description": "The user has not finished their message or turn or reached their end of utterance"
}
]
}
},
"typeVersion": 1.1
},
{
"id": "14dd091f-636b-4944-81b4-35da5f0f64b2",
"name": "响应用户",
"type": "n8n-nodes-base.telegram",
"position": [
1800,
320
],
"webhookId": "c095b0ea-c349-4ab7-8b16-efa5f4c22299",
"parameters": {
"text": "={{ $json.output }}",
"chatId": "={{ $('Session Ref').first().json.data.from }}",
"additionalFields": {
"parse_mode": "HTML",
"appendAttribution": false
}
},
"credentials": {
"telegramApi": {
"id": "Lk9x8q4NhLDMjfTV",
"name": "jimleuk_bot"
}
},
"typeVersion": 1.2
},
{
"id": "b6ae259c-9fc4-481a-bd6d-f1b3a0dc2d28",
"name": "便签",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1360,
-80
],
"parameters": {
"color": 7,
"width": 1020,
"height": 440,
"content": "## 1. 接收 Telegram 消息"
},
"typeVersion": 1
},
{
"id": "33c5c000-5d3e-459a-814e-f2e5669e9592",
"name": "便签1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1360,
400
],
"parameters": {
"color": 7,
"width": 1020,
"height": 560,
"content": "## 2. 判断是否为新消息"
},
"typeVersion": 1
},
{
"id": "939f8f46-c7c1-468f-af83-2c4f15fca09b",
"name": "便签2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-240,
780
],
"parameters": {
"color": 7,
"width": 660,
"height": 460,
"content": "## 3. 预测循环已在运行?让我们恢复!"
},
"typeVersion": 1
},
{
"id": "d36770f7-1992-4335-8e9d-01a73de44c0b",
"name": "便签3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-240,
-60
],
"parameters": {
"color": 7,
"width": 1340,
"height": 800,
"content": "## 2. 新话语开始?启动预测等待循环。"
},
"typeVersion": 1
},
{
"id": "d9dcc03f-8549-495e-969b-82c0f96c3057",
"name": "便签4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1160,
80
],
"parameters": {
"color": 7,
"width": 840,
"height": 660,
"content": "## 4. 仅在检测到话语结束时发送回复"
},
"typeVersion": 1
},
{
"id": "c242729b-0d95-4201-adee-b3a537d28eb1",
"name": "恢复等待节点",
"type": "n8n-nodes-base.httpRequest",
"position": [
140,
1020
],
"parameters": {
"url": "={{ $json.data.resumeUrl }}",
"options": {}
},
"typeVersion": 4.2
},
{
"id": "321e48ff-9389-408f-af97-e1590ce13e0c",
"name": "便签5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1860,
-300
],
"parameters": {
"width": 460,
"height": 1260,
"content": "## 试试看!"
},
"typeVersion": 1
},
{
"id": "f56fe585-7ece-49aa-813a-2d72b11d5d0f",
"name": "调用预测子工作流",
"type": "n8n-nodes-base.executeWorkflow",
"position": [
-640,
120
],
"parameters": {
"options": {
"waitForSubWorkflow": false
},
"workflowId": {
"__rl": true,
"mode": "id",
"value": "={{ $workflow.id }}"
},
"workflowInputs": {
"value": {
"from": "={{ $json.from }}",
"message": "={{ $json.message }}",
"createdAt": "={{ $json.createdAt }}"
},
"schema": [
{
"id": "from",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "from",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "message",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "message",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "createdAt",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "createdAt",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": true
}
},
"typeVersion": 1.2
},
{
"id": "6d24bc9e-223e-48f8-b32d-84cabf1febfc",
"name": "预测子工作流",
"type": "n8n-nodes-base.executeWorkflowTrigger",
"position": [
-1280,
700
],
"parameters": {
"workflowInputs": {
"values": [
{
"name": "from"
},
{
"name": "message"
},
{
"name": "createdAt"
}
]
}
},
"typeVersion": 1.1
},
{
"id": "f711ff8e-4b68-4379-8abe-33bc673bab1f",
"name": "获取更新的会话值",
"type": "n8n-nodes-base.set",
"position": [
-740,
700
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "ed66f412-aa70-4838-9295-bed652d62bfd",
"name": "data",
"type": "object",
"value": "={{\n{\n ...($('Get Session').item.json.data ?? {}),\n messages: [\n ...($('Get Session').item.json.data?.messages\n ? $('Get Session').item.json.data?.messages.parseJson()\n : []\n ),\n {\n value: $('Prediction Subworkflow').item.json.message,\n createdAt: $('Prediction Subworkflow').item.json.createdAt\n }\n ].toJsonString(),\n from: $('Prediction Subworkflow').item.json.from\n}\n}}"
}
]
}
},
"typeVersion": 3.4
}
],
"pinData": {},
"connections": {
"AI Agent": {
"main": [
[
{
"node": "Update Session2",
"type": "main",
"index": 0
}
]
]
},
"Get Values": {
"main": [
[
{
"node": "Call Prediction Subworkflow",
"type": "main",
"index": 0
}
]
]
},
"Get Session": {
"main": [
[
{
"node": "Update Session",
"type": "main",
"index": 0
}
]
]
},
"Is Waiting?": {
"main": [
[
{
"node": "Resume Wait Node",
"type": "main",
"index": 0
}
],
[]
]
},
"Session Ref": {
"main": [
[
{
"node": "Update Session1",
"type": "main",
"index": 0
}
]
]
},
"Get Session2": {
"main": [
[
{
"node": "Session Ended?",
"type": "main",
"index": 0
}
]
]
},
"Session Ended?": {
"main": [
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
],
[
{
"node": "Session Ref",
"type": "main",
"index": 0
}
]
]
},
"Update Session": {
"main": [
[
{
"node": "Get Updated Session Values",
"type": "main",
"index": 0
}
]
]
},
"Is Bot command?": {
"main": [
[],
[
{
"node": "Get Values",
"type": "main",
"index": 0
}
]
]
},
"Respond to User": {
"main": [
[]
]
},
"Update Session1": {
"main": [
[
{
"node": "Predict End of Utterance",
"type": "main",
"index": 0
}
]
]
},
"Update Session2": {
"main": [
[
{
"node": "Respond to User",
"type": "main",
"index": 0
}
]
]
},
"is New Session?": {
"main": [
[
{
"node": "Session Ref",
"type": "main",
"index": 0
}
],
[
{
"node": "Is Waiting?",
"type": "main",
"index": 0
}
]
]
},
"Telegram Trigger": {
"main": [
[
{
"node": "Is Bot command?",
"type": "main",
"index": 0
}
]
]
},
"Wait For Webhook": {
"main": [
[
{
"node": "Get Session2",
"type": "main",
"index": 0
}
]
]
},
"Redis Chat Memory": {
"ai_memory": [
[
{
"node": "AI Agent",
"type": "ai_memory",
"index": 0
}
]
]
},
"Prediction Subworkflow": {
"main": [
[
{
"node": "Get Session",
"type": "main",
"index": 0
}
]
]
},
"Google Gemini Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Predict End of Utterance": {
"main": [
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
],
[
{
"node": "Wait For Webhook",
"type": "main",
"index": 0
}
]
]
},
"Google Gemini Chat Model1": {
"ai_languageModel": [
[
{
"node": "Predict End of Utterance",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Get Updated Session Values": {
"main": [
[
{
"node": "is New Session?",
"type": "main",
"index": 0
}
]
]
},
"Call Prediction Subworkflow": {
"main": [
[]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
高级 - 客户支持, 人工智能
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
AI邮件分诊与GPT-4警报系统及Telegram通知
AI邮件分诊与GPT-4警报系统及Telegram通知
If
Set
Gmail
+22
104 节点Peter Joslyn
客户支持
使用Telegram、Google表格和AI创建产品满意度调查
通过Telegram、Google表格和AI创建产品满意度调查
If
Set
Redis
+12
40 节点Jimleuk
工程
Telegram AI 机器人转人工销售电话交接
Telegram AI 机器人转人工销售电话交接
If
Code
Redis
+12
39 节点Jimleuk
销售
YouTube RAG 搜索前端(使用 Apify、Qdrant 和 AI)
基于 Apify、Qdrant 和 AI 的 YouTube RAG 搜索前端
If
Set
Html
+23
62 节点Jimleuk
人工智能
通过Twilio和Redis缓冲消息增强客户聊天体验
使用Twilio和Redis缓冲消息功能增强客户聊天体验
If
Set
Wait
+9
18 节点Jimleuk
客户支持
LinkedIn和X病毒内容自动引擎
使用AI生成和发布自动创建LinkedIn和X的病毒内容
If
Set
Wait
+26
156 节点Diptamoy Barman
内容创作
工作流信息
难度等级
高级
节点数量29
分类2
节点类型15
作者
Jimleuk
@jimleukFreelance consultant based in the UK specialising in AI-powered automations. I work with select clients tackling their most challenging projects. For business enquiries, send me an email at hello@jimle.uk LinkedIn: https://www.linkedin.com/in/jimleuk/ X/Twitter: https://x.com/jimle_uk
外部链接
在 n8n.io 查看 →
分享此工作流